diff --git a/planemo/galaxy/workflows.py b/planemo/galaxy/workflows.py index 82ac66336..1fe1890ca 100644 --- a/planemo/galaxy/workflows.py +++ b/planemo/galaxy/workflows.py @@ -419,7 +419,7 @@ def _job_outputs_template_from_invocation(invocation_id, galaxy_url, galaxy_api_ download_function=user_gi.datasets.download_dataset, definition_style="outputs", ) - outputs[label] = {"element_tests": element_tests} + outputs[label] = {"elements": element_tests} return outputs diff --git a/planemo/runnable.py b/planemo/runnable.py index e852836d1..43d685b5a 100644 --- a/planemo/runnable.py +++ b/planemo/runnable.py @@ -342,6 +342,16 @@ def structured_test_data(self, run_response): """ +def elements_to_element_tests(output_expectations): + # I'm seeing this as a temporary fix, ultimately + # we should use pydantic to parse the tests and use + # pydantic models (or dataclasses) throughout the + # test framework. + for output_value in output_expectations.values(): + if isinstance(output_value, dict) and "elements" in output_value: + output_value["element_tests"] = output_value.pop("elements") + + class TestCase(AbstractTestCase): """Describe an abstract test case for a specified runnable.""" @@ -359,6 +369,7 @@ def __init__( self.runnable = runnable self.job_path = job_path self.job = job + elements_to_element_tests(output_expectations) self.output_expectations = output_expectations self.tests_directory = tests_directory self.index = index diff --git a/planemo/schema/__init__.py b/planemo/schema/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/planemo/schema/test_file_schema.json b/planemo/schema/test_file_schema.json new file mode 100644 index 000000000..4a4caddf3 --- /dev/null +++ b/planemo/schema/test_file_schema.json @@ -0,0 +1,3973 @@ +{ + "$defs": { + "AssertAttributeIs": { + "additionalProperties": false, + "description": "Asserts the XML ``attribute`` for the element (or tag) with the specified\nXPath-like ``path`` is the specified ``text``, e.g. ```xml <attribute_is\npath=\"outerElement/innerElement1\" attribute=\"foo\" text=\"bar\" /> ``` The\nassertion implicitly also asserts that an element matching ``path`` exists.\n\nWith ``negate`` the result of the assertion (on the equality) can be inverted (the\nimplicit assertion on the existence of the path is not affected).\n$attribute_list::5", + "properties": { + "path": { + "description": "Path to check for. Valid paths are the simplified subsets of XPath implemented by lxml.etree; https://lxml.de/xpathxslt.html for more information.", + "title": "Path", + "type": "string" + }, + "text": { + "description": "Text to check for.", + "title": "Text", + "type": "string" + }, + "negate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/PermissiveBooleanValue" + } + ], + "default": "false", + "description": "Negate the outcome of the assertion.", + "title": "Negate" + } + }, + "required": [ + "path", + "text" + ], + "title": "AssertAttributeIs", + "type": "object" + }, + "AssertAttributeMatches": { + "additionalProperties": false, + "description": "Asserts the XML ``attribute`` for the element (or tag) with the specified\nXPath-like ``path`` matches the regular expression specified by ``expression``,\ne.g. ```xml <attribute_matches path=\"outerElement/innerElement2\"\nattribute=\"foo2\" expression=\"bar\\d+\" /> ``` The assertion implicitly also\nasserts that an element matching ``path`` exists.\n\nWith ``negate`` the result of the assertion (on the matching) can be inverted (the\nimplicit assertion on the existence of the path is not affected).\n$attribute_list::5", + "properties": { + "path": { + "description": "Path to check for. Valid paths are the simplified subsets of XPath implemented by lxml.etree; https://lxml.de/xpathxslt.html for more information.", + "title": "Path", + "type": "string" + }, + "expression": { + "description": "The regular expression to use.", + "title": "Expression", + "type": "string" + }, + "negate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/PermissiveBooleanValue" + } + ], + "default": "false", + "description": "Negate the outcome of the assertion.", + "title": "Negate" + } + }, + "required": [ + "path", + "expression" + ], + "title": "AssertAttributeMatches", + "type": "object" + }, + "AssertElementText": { + "additionalProperties": false, + "description": "This tag allows the developer to recurisively specify additional assertions\nas child elements about just the text contained in the element specified by the\nXPath-like ``path``, e.g. ```xml <element_text\npath=\"BlastOutput_iterations/Iteration/Iteration_hits/Hit/Hit_def\">\n<not_has_text text=\"EDK72998.1\" /> </element_text> ``` The\nassertion implicitly also asserts that an element matching ``path`` exists.\n\nWith ``negate`` the result of the implicit assertions can be inverted.\nThe sub-assertions, which have their own ``negate`` attribute, are not affected\nby ``negate``.\n$attribute_list::5", + "properties": { + "has_text": { + "items": { + "$ref": "#/$defs/AssertHasText" + }, + "title": "Has Text", + "type": "array" + }, + "not_has_text": { + "items": { + "$ref": "#/$defs/AssertNotHasText" + }, + "title": "Not Has Text", + "type": "array" + }, + "has_text_matching": { + "items": { + "$ref": "#/$defs/AssertHasTextMatching" + }, + "title": "Has Text Matching", + "type": "array" + }, + "has_line": { + "items": { + "$ref": "#/$defs/AssertHasLine" + }, + "title": "Has Line", + "type": "array" + }, + "has_line_matching": { + "items": { + "$ref": "#/$defs/AssertHasLineMatching" + }, + "title": "Has Line Matching", + "type": "array" + }, + "has_n_lines": { + "items": { + "$ref": "#/$defs/AssertHasNlines" + }, + "title": "Has N Lines", + "type": "array" + }, + "path": { + "description": "Path to check for. Valid paths are the simplified subsets of XPath implemented by lxml.etree; https://lxml.de/xpathxslt.html for more information.", + "title": "Path", + "type": "string" + }, + "negate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/PermissiveBooleanValue" + } + ], + "default": "false", + "description": "Negate the outcome of the assertion.", + "title": "Negate" + } + }, + "required": [ + "path" + ], + "title": "AssertElementText", + "type": "object" + }, + "AssertElementTextIs": { + "additionalProperties": false, + "description": "Asserts the text of the XML element with the specified XPath-like ``path``\nis the specified ``text``, e.g. ```xml <element_text_is\npath=\"BlastOutput_program\" text=\"blastp\" /> ``` The assertion implicitly\nalso asserts that an element matching ``path`` exists.\n\nWith ``negate`` the result of the assertion (on the equality) can be inverted (the\nimplicit assertion on the existence of the path is not affected).\n$attribute_list::5", + "properties": { + "path": { + "description": "Path to check for. Valid paths are the simplified subsets of XPath implemented by lxml.etree; https://lxml.de/xpathxslt.html for more information.", + "title": "Path", + "type": "string" + }, + "text": { + "description": "Text to check for.", + "title": "Text", + "type": "string" + }, + "negate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/PermissiveBooleanValue" + } + ], + "default": "false", + "description": "Negate the outcome of the assertion.", + "title": "Negate" + } + }, + "required": [ + "path", + "text" + ], + "title": "AssertElementTextIs", + "type": "object" + }, + "AssertElementTextMatches": { + "additionalProperties": false, + "description": "Asserts the text of the XML element with the specified XPath-like ``path``\nmatches the regular expression defined by ``expression``, e.g. ```xml\n<element_text_matches path=\"BlastOutput_version\"\nexpression=\"BLASTP\\s+2\\.2.*\"/> ``` The assertion implicitly also asserts\nthat an element matching ``path`` exists.\n\nWith ``negate`` the result of the assertion (on the matching) can be inverted (the\nimplicit assertion on the existence of the path is not affected).\n$attribute_list::5", + "properties": { + "path": { + "description": "Path to check for. Valid paths are the simplified subsets of XPath implemented by lxml.etree; https://lxml.de/xpathxslt.html for more information.", + "title": "Path", + "type": "string" + }, + "expression": { + "description": "The regular expression to use.", + "title": "Expression", + "type": "string" + }, + "negate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/PermissiveBooleanValue" + } + ], + "default": "false", + "description": "Negate the outcome of the assertion.", + "title": "Negate" + } + }, + "required": [ + "path", + "expression" + ], + "title": "AssertElementTextMatches", + "type": "object" + }, + "AssertHasArchiveMember": { + "additionalProperties": false, + "description": "This tag allows to check if ``path`` is contained in a compressed file. The\npath is a regular expression that is matched against the full paths of the\nobjects in the compressed file (remember that \"matching\" means it is checked if\na prefix of the full path of an archive member is described by the regular\nexpression). Valid archive formats include ``.zip``, ``.tar``, and ``.tar.gz``.\nNote that.\n\ndepending on the archive creation method:\n- full paths of the members may be prefixed with ``./``\n- directories may be treated as empty files\n```xml\n<has_archive_member path=\"./path/to/my-file.txt\"/>\n```\nWith ``n`` and ``delta`` (or ``min`` and ``max``) assertions on the number of\narchive members matching ``path`` can be expressed. The following could be used,\ne.g., to assert an archive containing n&plusmn;1 elements out of which at least\n4 need to have a ``txt`` extension.\n```xml\n<has_archive_member path=\".*\" n=\"10\" delta=\"1\"/>\n<has_archive_member path=\".*\\.txt\" min=\"4\"/>\n```\nIn addition the tag can contain additional assertions as child elements about\nthe first member in the archive matching the regular expression ``path``. For\ninstance\n```xml\n<has_archive_member path=\".*/my-file.txt\">\n<not_has_text text=\"EDK72998.1\"/>\n</has_archive_member>\n```\nIf the ``all`` attribute is set to ``true`` then all archive members are subject\nto the assertions. Note that, archive members matching the ``path`` are sorted\nalphabetically.\nThe ``negate`` attribute of the ``has_archive_member`` assertion only affects\nthe asserts on the presence and number of matching archive members, but not any\nsub-assertions (which can offer the ``negate`` attribute on their own). The\ncheck if the file is an archive at all, which is also done by the function, is\nnot affected.\n$attribute_list::5", + "properties": { + "has_size": { + "items": { + "$ref": "#/$defs/AssertHasSize" + }, + "title": "Has Size", + "type": "array" + }, + "has_text": { + "items": { + "$ref": "#/$defs/AssertHasText" + }, + "title": "Has Text", + "type": "array" + }, + "not_has_text": { + "items": { + "$ref": "#/$defs/AssertNotHasText" + }, + "title": "Not Has Text", + "type": "array" + }, + "has_text_matching": { + "items": { + "$ref": "#/$defs/AssertHasTextMatching" + }, + "title": "Has Text Matching", + "type": "array" + }, + "has_line": { + "items": { + "$ref": "#/$defs/AssertHasLine" + }, + "title": "Has Line", + "type": "array" + }, + "has_line_matching": { + "items": { + "$ref": "#/$defs/AssertHasLineMatching" + }, + "title": "Has Line Matching", + "type": "array" + }, + "has_n_lines": { + "items": { + "$ref": "#/$defs/AssertHasNlines" + }, + "title": "Has N Lines", + "type": "array" + }, + "has_n_columns": { + "items": { + "$ref": "#/$defs/AssertHasNcolumns" + }, + "title": "Has N Columns", + "type": "array" + }, + "has_json_property_with_value": { + "items": { + "$ref": "#/$defs/AssertHasJsonPropertyWithValue" + }, + "title": "Has Json Property With Value", + "type": "array" + }, + "has_json_property_with_text": { + "items": { + "$ref": "#/$defs/AssertHasJsonPropertyWithText" + }, + "title": "Has Json Property With Text", + "type": "array" + }, + "is_valid_xml": { + "items": { + "$ref": "#/$defs/AssertIsValidXml" + }, + "title": "Is Valid Xml", + "type": "array" + }, + "xml_element": { + "items": { + "$ref": "#/$defs/AssertXmlelement" + }, + "title": "Xml Element", + "type": "array" + }, + "has_element_with_path": { + "items": { + "$ref": "#/$defs/AssertHasElementWithPath" + }, + "title": "Has Element With Path", + "type": "array" + }, + "has_n_elements_with_path": { + "items": { + "$ref": "#/$defs/AssertHasNelementsWithPath" + }, + "title": "Has N Elements With Path", + "type": "array" + }, + "element_text_matches": { + "items": { + "$ref": "#/$defs/AssertElementTextMatches" + }, + "title": "Element Text Matches", + "type": "array" + }, + "element_text_is": { + "items": { + "$ref": "#/$defs/AssertElementTextIs" + }, + "title": "Element Text Is", + "type": "array" + }, + "attribute_matches": { + "items": { + "$ref": "#/$defs/AssertAttributeMatches" + }, + "title": "Attribute Matches", + "type": "array" + }, + "attribute_is": { + "items": { + "$ref": "#/$defs/AssertAttributeIs" + }, + "title": "Attribute Is", + "type": "array" + }, + "element_text": { + "items": { + "$ref": "#/$defs/AssertElementText" + }, + "title": "Element Text", + "type": "array" + }, + "has_h5_keys": { + "items": { + "$ref": "#/$defs/AssertHasH5Keys" + }, + "title": "Has H5 Keys", + "type": "array" + }, + "has_h5_attribute": { + "items": { + "$ref": "#/$defs/AssertHasH5Attribute" + }, + "title": "Has H5 Attribute", + "type": "array" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The regular expression specifying the archive member.", + "title": "Path" + }, + "all": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/PermissiveBooleanValue" + } + ], + "default": "false", + "description": "Check the sub-assertions for all paths matching the path. Default: false, i.e. only the first", + "title": "All" + }, + "n": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Desired number, can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "N" + }, + "delta": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Delta" + }, + "min": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Min" + }, + "max": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Max" + } + }, + "title": "AssertHasArchiveMember", + "type": "object" + }, + "AssertHasElementWithPath": { + "additionalProperties": false, + "description": "Asserts the XML output contains at least one element (or tag) with the\nspecified XPath-like ``path``, e.g. ```xml <has_element_with_path\npath=\"BlastOutput_param/Parameters/Parameters_matrix\" /> ``` With ``negate``\nthe result of the assertion can be inverted.\n\n$attribute_list::5", + "properties": { + "path": { + "description": "Path to check for. Valid paths are the simplified subsets of XPath implemented by lxml.etree; https://lxml.de/xpathxslt.html for more information.", + "title": "Path", + "type": "string" + }, + "negate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/PermissiveBooleanValue" + } + ], + "default": "false", + "description": "Negate the outcome of the assertion.", + "title": "Negate" + } + }, + "required": [ + "path" + ], + "title": "AssertHasElementWithPath", + "type": "object" + }, + "AssertHasH5Attribute": { + "additionalProperties": false, + "description": "Asserts HDF5 output contains the specified ``value`` for an attribute (``key``), e.g.\n```xml\n<has_h5_attribute key=\"nchroms\" value=\"15\" />\n```\n$attribute_list::5", + "properties": { + "key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "HDF5 attribute to check value of.", + "title": "Key" + }, + "value": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Expected value of HDF5 attribute to check.", + "title": "Value" + } + }, + "title": "AssertHasH5Attribute", + "type": "object" + }, + "AssertHasH5Keys": { + "additionalProperties": false, + "description": "Asserts HDF5 output has a set of attributes (``keys``), specified as a\ncomma-separated list, e.g.\n```xml\n<has_h5_keys keys=\"bins,chroms,indexes,pixels,chroms/lengths\" />\n```\n$attribute_list::5", + "properties": { + "keys": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Comma-separated list of HDF5 attributes to check for.", + "title": "Keys" + } + }, + "title": "AssertHasH5Keys", + "type": "object" + }, + "AssertHasJsonPropertyWithText": { + "additionalProperties": false, + "description": "Asserts the JSON document contains a property or key with the specified text\n(i.e. string) value.\n\n```xml\n<has_json_property_with_text property=\"color\" text=\"red\" />\n```\n$attribute_list::5", + "properties": { + "property": { + "description": "JSON property to search the target for.", + "title": "Property", + "type": "string" + }, + "text": { + "description": "Text value to search for.", + "title": "Text", + "type": "string" + } + }, + "required": [ + "property", + "text" + ], + "title": "AssertHasJsonPropertyWithText", + "type": "object" + }, + "AssertHasJsonPropertyWithValue": { + "additionalProperties": false, + "description": "Asserts the JSON document contains a property or key with the specified JSON\nvalue.\n\n```xml\n<has_json_property_with_value property=\"skipped_columns\" value=\"[1, 3, 5]\" />\n```\n$attribute_list::5", + "properties": { + "property": { + "description": "JSON property to search the target for.", + "title": "Property", + "type": "string" + }, + "value": { + "description": "JSON-ified value to search for. This will be converted from an XML string to JSON with Python's json.loads function.", + "title": "Value", + "type": "string" + } + }, + "required": [ + "property", + "value" + ], + "title": "AssertHasJsonPropertyWithValue", + "type": "object" + }, + "AssertHasLine": { + "additionalProperties": false, + "description": "Asserts a line matching the specified string (``line``) appears in the\noutput (e.g. ``<has_line line=\"A full example line.\" />``).\n\nIf the ``line`` is expected\nto occur a particular number of times, this value can be specified using ``n``.\nOptionally also with a certain ``delta``. Alternatively the range of expected\noccurences can be specified by ``min`` and/or ``max``.\n$attribute_list::5", + "properties": { + "line": { + "description": "The line to check for", + "title": "Line", + "type": "string" + }, + "n": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Desired number, can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "N" + }, + "delta": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Delta" + }, + "min": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Min" + }, + "max": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Max" + }, + "negate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/PermissiveBooleanValue" + } + ], + "default": "false", + "description": "Negate the outcome of the assertion.", + "title": "Negate" + } + }, + "required": [ + "line" + ], + "title": "AssertHasLine", + "type": "object" + }, + "AssertHasLineMatching": { + "additionalProperties": false, + "description": "Asserts a line matching the specified regular expression (``expression``)\nappears in the output (e.g. ``<has_line_matching\nexpression=\".*\\s+127489808\\s+127494553\" />``).\n\nIf a particular number of matching lines is expected, this value can be\nspecified using ``n``. Optionally also with ``delta``. Alternatively the range\nof expected occurences can be specified by ``min`` and/or ``max``.\n$attribute_list::5", + "properties": { + "expression": { + "description": "Regular expression to check for", + "title": "Expression", + "type": "string" + }, + "n": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Desired number, can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "N" + }, + "delta": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Delta" + }, + "min": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Min" + }, + "max": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Max" + }, + "negate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/PermissiveBooleanValue" + } + ], + "default": "false", + "description": "Negate the outcome of the assertion.", + "title": "Negate" + } + }, + "required": [ + "expression" + ], + "title": "AssertHasLineMatching", + "type": "object" + }, + "AssertHasNcolumns": { + "additionalProperties": false, + "description": "Asserts tabular output (actually only the first line) contains the specified\nnumber (``n``) of columns (e.g. ``<has_n_columns n=\"3\"/>``) optionally\nalso with ``delta``.\n\nAlternatively the range of expected occurences can be specified by\n``min`` and/or ``max``. Optionally a column separator (``sep``, default is\n``\\t``) `and comment character(s) can be specified (``comment``, default is\nempty string), then the first non-comment line is used for determining the\nnumber of columns.\n$attribute_list::5", + "properties": { + "n": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Desired number, can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "N" + }, + "delta": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Delta" + }, + "min": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Min" + }, + "max": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Max" + }, + "negate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/PermissiveBooleanValue" + } + ], + "default": "false", + "description": "Negate the outcome of the assertion.", + "title": "Negate" + }, + "sep": { + "default": " ", + "description": "Separator defining columns, default: tab", + "title": "Sep", + "type": "string" + }, + "comment": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Comment character(s) used to skip comment lines (which should not be used for counting columns)", + "title": "Comment" + } + }, + "title": "AssertHasNcolumns", + "type": "object" + }, + "AssertHasNelementsWithPath": { + "additionalProperties": false, + "description": "Asserts the XML output contains the specified number (``n``, optionally with\n``delta``) of elements (or tags) with the specified XPath-like ``path``, e.g.\n```xml <has_n_elements_with_path n=\"9\"\npath=\"BlastOutput_iterations/Iteration/Iteration_hits/Hit/Hit_num\" /> ```\nAlternatively to ``n`` and ``delta`` also the ``min`` and ``max`` attributes\ncan be used to specify the range of the expected number of occurences.\n\nWith ``negate`` the result of the assertion can be inverted.\n$attribute_list::5", + "properties": { + "path": { + "description": "Path to check for. Valid paths are the simplified subsets of XPath implemented by lxml.etree; https://lxml.de/xpathxslt.html for more information.", + "title": "Path", + "type": "string" + }, + "n": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Desired number, can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "N" + }, + "delta": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Delta" + }, + "min": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Min" + }, + "max": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Max" + }, + "negate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/PermissiveBooleanValue" + } + ], + "default": "false", + "description": "Negate the outcome of the assertion.", + "title": "Negate" + } + }, + "required": [ + "path" + ], + "title": "AssertHasNelementsWithPath", + "type": "object" + }, + "AssertHasNlines": { + "additionalProperties": false, + "description": "Asserts that an output contains ``n`` lines, allowing for a difference of\n``delta`` (default is 0), e.g. ``<has_n_lines n=\"3\" delta=\"1\"/>``.\n\nAlternatively the range of expected occurences can be specified by ``min``\nand/or ``max``.\n$attribute_list::5", + "properties": { + "n": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Desired number, can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "N" + }, + "delta": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Delta" + }, + "min": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Min" + }, + "max": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Max" + }, + "negate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/PermissiveBooleanValue" + } + ], + "default": "false", + "description": "Negate the outcome of the assertion.", + "title": "Negate" + } + }, + "title": "AssertHasNlines", + "type": "object" + }, + "AssertHasSize": { + "additionalProperties": false, + "description": "Asserts the output has a specific size (in bytes) of ``value`` plus minus\n``delta``, e.g. ``<has_size value=\"10000\" delta=\"100\" />``.\n\nAlternatively the range of the expected size can be specified by ``min`` and/or\n``max``.\n$attribute_list::5", + "properties": { + "value": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Desired size of the output (in bytes), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Value" + }, + "delta": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Maximum allowed size difference (default is 0). The observed size has to be in the range ``value +- delta``. Can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Delta" + }, + "min": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Minimum expected size, can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Min" + }, + "max": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Maximum expected size, can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Max" + }, + "negate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/PermissiveBooleanValue" + } + ], + "default": "false", + "description": "Negate the outcome of the assertion.", + "title": "Negate" + } + }, + "title": "AssertHasSize", + "type": "object" + }, + "AssertHasText": { + "additionalProperties": false, + "description": "Asserts the specified ``text`` appears in the output (e.g. ``<has_text\ntext=\"chr7\">``).\n\nIf the ``text`` is expected to occur a particular number of\ntimes, this value can be specified using ``n``. Optionally also with a certain\n``delta``. Alternatively the range of expected occurences can be specified by\n``min`` and/or ``max``.\n$attribute_list::5", + "properties": { + "text": { + "description": "Text to check for", + "title": "Text", + "type": "string" + }, + "n": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Desired number, can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "N" + }, + "delta": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Delta" + }, + "min": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Min" + }, + "max": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Max" + }, + "negate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/PermissiveBooleanValue" + } + ], + "default": "false", + "description": "Negate the outcome of the assertion.", + "title": "Negate" + } + }, + "required": [ + "text" + ], + "title": "AssertHasText", + "type": "object" + }, + "AssertHasTextMatching": { + "additionalProperties": false, + "description": "Asserts text matching the specified regular expression (``expression``)\nappears in the output (e.g. ``<has_text_matching expression=\"1274\\d+53\"\n/>`` ).\n\nIf the\nregular expression is expected to match a particular number of times, this value\ncan be specified using ``n``. Note only non-overlapping occurences are counted.\nOptionally also with a certain ``delta``. Alternatively the range of expected\noccurences can be specified by ``min`` and/or ``max``.\n$attribute_list::5", + "properties": { + "expression": { + "description": "Regular expression to check for", + "title": "Expression", + "type": "string" + }, + "n": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Desired number, can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "N" + }, + "delta": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Delta" + }, + "min": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Min" + }, + "max": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Max" + }, + "negate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/PermissiveBooleanValue" + } + ], + "default": "false", + "description": "Negate the outcome of the assertion.", + "title": "Negate" + } + }, + "required": [ + "expression" + ], + "title": "AssertHasTextMatching", + "type": "object" + }, + "AssertIsValidXml": { + "additionalProperties": false, + "description": "Asserts the output is a valid XML file (e.g. ``<is_valid_xml />``).\n\n$attribute_list::5", + "properties": {}, + "title": "AssertIsValidXml", + "type": "object" + }, + "AssertNotHasText": { + "additionalProperties": false, + "description": "Asserts the specified ``text`` does not appear in the output (e.g.\n``<not_has_text text=\"chr8\" />``).\n\n$attribute_list::5", + "properties": { + "text": { + "description": "Text to check for", + "title": "Text", + "type": "string" + } + }, + "required": [ + "text" + ], + "title": "AssertNotHasText", + "type": "object" + }, + "AssertXmlelement": { + "additionalProperties": false, + "description": "Assert if the XML file contains element(s) or tag(s) with the specified\n[XPath-like ``path``](https://lxml.de/xpathxslt.html). If ``n`` and ``delta``\nor ``min`` and ``max`` are given also the number of occurences is checked.\n```xml\n<assert_contents>\n<xml_element path=\"./elem\"/>\n<xml_element path=\"./elem/more[2]\"/>\n<xml_element path=\".//more\" n=\"3\" delta=\"1\"/>\n</assert_contents>\n```\nWith ``negate=\"true\"`` the outcome of the assertions wrt the precence and number\nof ``path`` can be negated. If there are any sub assertions then check them against\n- the content of the attribute ``attribute``\n- the element's text if no attribute is given\n```xml\n<assert_contents>\n<xml_element path=\"./elem/more[2]\" attribute=\"name\">\n<has_text_matching expression=\"foo$\"/>\n</xml_element>\n</assert_contents>\n```\nSub-assertions are not subject to the ``negate`` attribute of ``xml_element``.\nIf ``all`` is ``true`` then the sub assertions are checked for all occurences.\nNote that all other XML assertions can be expressed by this assertion (Galaxy\nalso implements the other assertions by calling this one).\n$attribute_list::5", + "properties": { + "path": { + "description": "Path to check for. Valid paths are the simplified subsets of XPath implemented by lxml.etree; https://lxml.de/xpathxslt.html for more information.", + "title": "Path", + "type": "string" + }, + "all": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/PermissiveBooleanValue" + } + ], + "default": "false", + "description": "Check the sub-assertions for all paths matching the path. Default: false, i.e. only the first", + "title": "All" + }, + "attribute": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The name of the attribute to apply sub-assertion on. If not given then the element text is used", + "title": "Attribute" + }, + "n": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Desired number, can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "N" + }, + "delta": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Delta" + }, + "min": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Min" + }, + "max": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", + "title": "Max" + }, + "negate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/PermissiveBooleanValue" + } + ], + "default": "false", + "description": "Negate the outcome of the assertion.", + "title": "Negate" + } + }, + "required": [ + "path" + ], + "title": "AssertXmlelement", + "type": "object" + }, + "Collection": { + "properties": { + "class": { + "const": "Collection", + "title": "Class" + }, + "collection_type": { + "default": "list", + "title": "Collection Type", + "type": "string" + }, + "elements": { + "items": { + "anyOf": [ + { + "$ref": "#/$defs/CollectionElement" + }, + { + "$ref": "#/$defs/LocationFileElement" + }, + { + "$ref": "#/$defs/PathFileElement" + } + ] + }, + "title": "Elements", + "type": "array" + } + }, + "required": [ + "class", + "elements" + ], + "title": "Collection", + "type": "object" + }, + "CollectionElement": { + "properties": { + "class": { + "const": "Collection", + "title": "Class" + }, + "identifier": { + "title": "Identifier", + "type": "string" + }, + "elements": { + "items": { + "anyOf": [ + { + "$ref": "#/$defs/CollectionElement" + }, + { + "$ref": "#/$defs/LocationFileElement" + }, + { + "$ref": "#/$defs/PathFileElement" + } + ] + }, + "title": "Elements", + "type": "array" + }, + "type": { + "default": "list", + "title": "Type", + "type": "string" + } + }, + "required": [ + "class", + "identifier", + "elements" + ], + "title": "CollectionElement", + "type": "object" + }, + "Job": { + "anyOf": [ + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "integer" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "$ref": "#/$defs/Collection" + }, + { + "$ref": "#/$defs/LocationFile" + }, + { + "$ref": "#/$defs/PathFile" + }, + { + "type": "null" + } + ] + }, + "type": "object" + }, + { + "type": "string" + } + ], + "title": "Job" + }, + "LocationFile": { + "additionalProperties": false, + "properties": { + "class": { + "const": "File", + "title": "Class" + }, + "filetype": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Datatype extension for uploaded dataset.", + "title": "Filetype" + }, + "dbkey": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Dbkey" + }, + "decompress": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": false, + "title": "Decompress" + }, + "to_posix_line": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "To Posix Line" + }, + "space_to_tab": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If set, spaces in text datasets will be converted to tabs.", + "title": "Space To Tab" + }, + "deferred": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If set, datasets will not be stored on disk, but will be downloaded when used as inputs. Can only be used if a remote URI is used instead of a local file.", + "title": "Deferred" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Name of dataset in history.", + "title": "Name" + }, + "info": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Info" + }, + "tags": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Tags to apply to uploaded dataset.", + "title": "Tags" + }, + "composite_data": { + "anyOf": [ + { + "items": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Composite Data" + }, + "location": { + "title": "Location", + "type": "string" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Path" + } + }, + "required": [ + "class", + "location" + ], + "title": "LocationFile", + "type": "object" + }, + "LocationFileElement": { + "additionalProperties": false, + "properties": { + "class": { + "const": "File", + "title": "Class" + }, + "filetype": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Datatype extension for uploaded dataset.", + "title": "Filetype" + }, + "dbkey": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Dbkey" + }, + "decompress": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": false, + "title": "Decompress" + }, + "to_posix_line": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "To Posix Line" + }, + "space_to_tab": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If set, spaces in text datasets will be converted to tabs.", + "title": "Space To Tab" + }, + "deferred": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If set, datasets will not be stored on disk, but will be downloaded when used as inputs. Can only be used if a remote URI is used instead of a local file.", + "title": "Deferred" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Name of dataset in history.", + "title": "Name" + }, + "info": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Info" + }, + "tags": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Tags to apply to uploaded dataset.", + "title": "Tags" + }, + "composite_data": { + "anyOf": [ + { + "items": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Composite Data" + }, + "identifier": { + "title": "Identifier", + "type": "string" + }, + "location": { + "title": "Location", + "type": "string" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Path" + } + }, + "required": [ + "class", + "identifier", + "location" + ], + "title": "LocationFileElement", + "type": "object" + }, + "PathFile": { + "additionalProperties": false, + "properties": { + "class": { + "const": "File", + "title": "Class" + }, + "filetype": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Datatype extension for uploaded dataset.", + "title": "Filetype" + }, + "dbkey": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Dbkey" + }, + "decompress": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": false, + "title": "Decompress" + }, + "to_posix_line": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "To Posix Line" + }, + "space_to_tab": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If set, spaces in text datasets will be converted to tabs.", + "title": "Space To Tab" + }, + "deferred": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If set, datasets will not be stored on disk, but will be downloaded when used as inputs. Can only be used if a remote URI is used instead of a local file.", + "title": "Deferred" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Name of dataset in history.", + "title": "Name" + }, + "info": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Info" + }, + "tags": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Tags to apply to uploaded dataset.", + "title": "Tags" + }, + "composite_data": { + "anyOf": [ + { + "items": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Composite Data" + }, + "path": { + "title": "Path", + "type": "string" + } + }, + "required": [ + "class", + "path" + ], + "title": "PathFile", + "type": "object" + }, + "PathFileElement": { + "additionalProperties": false, + "properties": { + "class": { + "const": "File", + "title": "Class" + }, + "filetype": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Datatype extension for uploaded dataset.", + "title": "Filetype" + }, + "dbkey": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Dbkey" + }, + "decompress": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": false, + "title": "Decompress" + }, + "to_posix_line": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "To Posix Line" + }, + "space_to_tab": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If set, spaces in text datasets will be converted to tabs.", + "title": "Space To Tab" + }, + "deferred": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If set, datasets will not be stored on disk, but will be downloaded when used as inputs. Can only be used if a remote URI is used instead of a local file.", + "title": "Deferred" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Name of dataset in history.", + "title": "Name" + }, + "info": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Info" + }, + "tags": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Tags to apply to uploaded dataset.", + "title": "Tags" + }, + "composite_data": { + "anyOf": [ + { + "items": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Composite Data" + }, + "identifier": { + "title": "Identifier", + "type": "string" + }, + "path": { + "title": "Path", + "type": "string" + } + }, + "required": [ + "class", + "identifier", + "path" + ], + "title": "PathFileElement", + "type": "object" + }, + "PermissiveBooleanValue": { + "enum": [ + "0", + "1", + "true", + "false", + "True", + "False", + "yes", + "no" + ], + "title": "PermissiveBooleanValue", + "type": "string" + }, + "Test": { + "additionalProperties": false, + "properties": { + "doc": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Describes the purpose of the test.", + "title": "Doc" + }, + "job": { + "allOf": [ + { + "$ref": "#/$defs/Job" + } + ], + "description": "Defines job to execute. Can be a path to a file or an line dictionary describing the job inputs." + }, + "outputs": { + "additionalProperties": { + "anyOf": [ + { + "$ref": "#/$defs/TestOutputElement" + }, + { + "$ref": "#/$defs/TestOutput" + }, + { + "$ref": "#/$defs/TestOutputCollection" + }, + { + "$ref": "#/$defs/TestOutputCollectionDeprecated" + }, + { + "type": "string" + }, + { + "type": "integer" + }, + { + "type": "number" + }, + { + "type": "boolean" + } + ] + }, + "description": "Defines assertions about outputs (datasets, collections or parameters). Each key corresponds to a labeled output, values are dictionaries describing the expected output.", + "title": "Outputs", + "type": "object" + } + }, + "required": [ + "job", + "outputs" + ], + "title": "Test", + "type": "object" + }, + "TestAssertions": { + "additionalProperties": false, + "description": "This tag set defines a sequence of checks or assertions to run against the\ntarget output.\n\nThis tag requires no attributes, but child tags should be used to\ndefine the assertions to make about the output. The functional test framework\nmakes it easy to extend Galaxy with such tags, the following table summarizes\nmany of the default assertion tags that come with Galaxy and examples of each\ncan be found below.\nThe implementation of these tags are simply Python functions defined in the\n[/lib/galaxy/tool_util/verify/asserts](https://github.com/galaxyproject/galaxy/tree/dev/lib/galaxy/tool_util/verify/asserts)\nmodule.", + "properties": { + "has_size": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/AssertHasSize" + }, + "type": "array" + }, + { + "$ref": "#/$defs/AssertHasSize" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Has Size" + }, + "has_text": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/AssertHasText" + }, + "type": "array" + }, + { + "$ref": "#/$defs/AssertHasText" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Has Text" + }, + "not_has_text": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/AssertNotHasText" + }, + "type": "array" + }, + { + "$ref": "#/$defs/AssertNotHasText" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Not Has Text" + }, + "has_text_matching": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/AssertHasTextMatching" + }, + "type": "array" + }, + { + "$ref": "#/$defs/AssertHasTextMatching" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Has Text Matching" + }, + "has_line": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/AssertHasLine" + }, + "type": "array" + }, + { + "$ref": "#/$defs/AssertHasLine" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Has Line" + }, + "has_line_matching": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/AssertHasLineMatching" + }, + "type": "array" + }, + { + "$ref": "#/$defs/AssertHasLineMatching" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Has Line Matching" + }, + "has_n_lines": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/AssertHasNlines" + }, + "type": "array" + }, + { + "$ref": "#/$defs/AssertHasNlines" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Has N Lines" + }, + "has_n_columns": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/AssertHasNcolumns" + }, + "type": "array" + }, + { + "$ref": "#/$defs/AssertHasNcolumns" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Has N Columns" + }, + "has_archive_member": { + "items": { + "$ref": "#/$defs/AssertHasArchiveMember" + }, + "title": "Has Archive Member", + "type": "array" + }, + "is_valid_xml": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/AssertIsValidXml" + }, + "type": "array" + }, + { + "$ref": "#/$defs/AssertIsValidXml" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Is Valid Xml" + }, + "xml_element": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/AssertXmlelement" + }, + "type": "array" + }, + { + "$ref": "#/$defs/AssertXmlelement" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Xml Element" + }, + "has_element_with_path": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/AssertHasElementWithPath" + }, + "type": "array" + }, + { + "$ref": "#/$defs/AssertHasElementWithPath" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Has Element With Path" + }, + "has_n_elements_with_path": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/AssertHasNelementsWithPath" + }, + "type": "array" + }, + { + "$ref": "#/$defs/AssertHasNelementsWithPath" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Has N Elements With Path" + }, + "element_text_matches": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/AssertElementTextMatches" + }, + "type": "array" + }, + { + "$ref": "#/$defs/AssertElementTextMatches" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Element Text Matches" + }, + "element_text_is": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/AssertElementTextIs" + }, + "type": "array" + }, + { + "$ref": "#/$defs/AssertElementTextIs" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Element Text Is" + }, + "attribute_matches": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/AssertAttributeMatches" + }, + "type": "array" + }, + { + "$ref": "#/$defs/AssertAttributeMatches" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Attribute Matches" + }, + "attribute_is": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/AssertAttributeIs" + }, + "type": "array" + }, + { + "$ref": "#/$defs/AssertAttributeIs" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Attribute Is" + }, + "element_text": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/AssertElementText" + }, + "type": "array" + }, + { + "$ref": "#/$defs/AssertElementText" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Element Text" + }, + "has_json_property_with_value": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/AssertHasJsonPropertyWithValue" + }, + "type": "array" + }, + { + "$ref": "#/$defs/AssertHasJsonPropertyWithValue" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Has Json Property With Value" + }, + "has_json_property_with_text": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/AssertHasJsonPropertyWithText" + }, + "type": "array" + }, + { + "$ref": "#/$defs/AssertHasJsonPropertyWithText" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Has Json Property With Text" + }, + "has_h5_keys": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/AssertHasH5Keys" + }, + "type": "array" + }, + { + "$ref": "#/$defs/AssertHasH5Keys" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Has H5 Keys" + }, + "has_h5_attribute": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/AssertHasH5Attribute" + }, + "type": "array" + }, + { + "$ref": "#/$defs/AssertHasH5Attribute" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Has H5 Attribute" + } + }, + "title": "TestAssertions", + "type": "object" + }, + "TestDiscoveredDataset": { + "additionalProperties": false, + "description": "This directive specifies a test for an output's discovered dataset.\n\nIt acts as an\n``output`` test tag in many ways and can define any tests of that tag (e.g.\n``assert_contents``, ``value``, ``compare``, ``md5``, ``checksum``, ``metadata``, etc...).\n### Example\nThe functional test tool\n[multi_output_assign_primary.xml](https://github.com/galaxyproject/galaxy/blob/dev/test/functional/tools/multi_output_assign_primary.xml)\nprovides a demonstration of using this tag.\n```xml\n<outputs>\n<data format=\"tabular\" name=\"sample\">\n<discover_datasets pattern=\"(?P&lt;designation&gt;.+)\\.report\\.tsv\" ext=\"tabular\" visible=\"true\" assign_primary_output=\"true\" />\n</data>\n</outputs>\n<test>\n<param name=\"num_param\" value=\"7\" />\n<param name=\"input\" ftype=\"txt\" value=\"simple_line.txt\"/>\n<output name=\"sample\">\n<assert_contents>\n<has_line line=\"1\" />\n</assert_contents>\n<!-- no sample1 it was consumed by named output \"sample\" -->\n<discovered_dataset designation=\"sample2\" ftype=\"tabular\">\n<assert_contents><has_line line=\"2\" /></assert_contents>\n</discovered_dataset>\n<discovered_dataset designation=\"sample3\" ftype=\"tabular\">\n<assert_contents><has_line line=\"3\" /></assert_contents>\n</discovered_dataset>\n</output>\n</test>\n```\nNote that this tool uses ``assign_primary_output=\"true\"`` for ``<discover_datasets>``. Hence, the content of the first discovered dataset (which is the first in the alphabetically sorted list of discovered designations) is checked directly in the ``<output>`` tag of the test.", + "properties": { + "class": { + "anyOf": [ + { + "const": "File" + }, + { + "type": "null" + } + ], + "default": "File", + "title": "Class" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Path" + }, + "discovered_dataset": { + "items": { + "$ref": "#/$defs/TestDiscoveredDataset" + }, + "title": "Discovered Dataset", + "type": "array" + }, + "asserts": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/TestAssertions" + }, + "type": "array" + }, + { + "$ref": "#/$defs/TestAssertions" + }, + { + "type": "null" + } + ], + "default": null, + "description": "$assertions\n### Examples\nThe following demonstrates a wide variety of text-based and tabular\nassertion statements.\n```xml\n<output name=\"out_file1\">\n<assert_contents>\n<has_text text=\"chr7\" />\n<not_has_text text=\"chr8\" />\n<has_text_matching expression=\"1274\\d+53\" />\n<has_line_matching expression=\".*\\s+127489808\\s+127494553\" />\n<!-- &#009; is XML escape code for tab -->\n<has_line line=\"chr7&#009;127471195&#009;127489808\" />\n<has_n_columns n=\"3\" />\n</assert_contents>\n</output>\n```\nThe following demonstrates a wide variety of XML assertion statements.\n```xml\n<output name=\"out_file1\">\n<assert_contents>\n<is_valid_xml />\n<has_element_with_path path=\"BlastOutput_param/Parameters/Parameters_matrix\" />\n<has_n_elements_with_path n=\"9\" path=\"BlastOutput_iterations/Iteration/Iteration_hits/Hit/Hit_num\" />\n<element_text_matches path=\"BlastOutput_version\" expression=\"BLASTP\\s+2\\.2.*\" />\n<element_text_is path=\"BlastOutput_program\" text=\"blastp\" />\n<element_text path=\"BlastOutput_iterations/Iteration/Iteration_hits/Hit/Hit_def\">\n<not_has_text text=\"EDK72998.1\" />\n<has_text_matching expression=\"ABK[\\d\\.]+\" />\n</element_text>\n</assert_contents>\n</output>\n```\nThe following demonstrates verifying XML content with XPath-like expressions.\n```xml\n<output name=\"out_file1\">\n<assert_contents>\n<attribute_is path=\"outerElement/innerElement1\" attribute=\"foo\" text=\"bar\" />\n<attribute_matches path=\"outerElement/innerElement2\" attribute=\"foo2\" expression=\"bar\\d+\" />\n</assert_contents>\n</output>\n```", + "title": "Asserts" + }, + "extra_files": { + "items": { + "$ref": "#/$defs/TestExtraFile" + }, + "title": "Extra Files", + "type": "array" + }, + "metadata": { + "items": { + "$ref": "#/$defs/TestOutputMetadata" + }, + "title": "Metadata", + "type": "array" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "This value is the same as the value of the ``name`` attribute of the ``<data>``\ntag set contained within the tool's ``<outputs>`` tag set.", + "title": "Name" + }, + "file": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If specified, this value is the name of the output file stored in the target\n``test-data`` directory which will be used to compare the results of executing\nthe tool via the functional test framework.", + "title": "File" + }, + "value_json": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If specified, this value will be loaded as JSON and compared against the output\ngenerated as JSON. This can be useful for testing tool outputs that are not files.", + "title": "Value Json" + }, + "ftype": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If specified, this value will be checked against the corresponding output's\ndata type. If these do not match, the test will fail.", + "title": "Ftype" + }, + "sort": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/PermissiveBooleanValue" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Applies only if ``compare`` is ``diff``, ``re_match`` or ``re_match_multiline``. This flag causes the lines of the history data set to be sorted before the comparison. In case of ``diff`` and ``re_match`` also the local file is sorted. This could be\nuseful for non-deterministic output.", + "title": "Sort" + }, + "value": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "An alias for ``file``.", + "title": "Value" + }, + "md5": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If specified, the target output's MD5 hash should match the value specified\nhere. For large static files it may be inconvenient to upload the entiry file\nand this can be used instead.", + "title": "Md5" + }, + "checksum": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If specified, the target output's checksum should match the value specified\nhere. This value should have the form ``hash_type$hash_value``\n(e.g. ``sha1$8156d7ca0f46ed7abac98f82e36cfaddb2aca041``). For large static files\nit may be inconvenient to upload the entiry file and this can be used instead.", + "title": "Checksum" + }, + "compare": { + "anyOf": [ + { + "$ref": "#/$defs/TestOutputCompareType" + }, + { + "type": "null" + } + ], + "default": null + }, + "lines_diff": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Applies only if ``compare`` is set to ``diff``, ``re_match``, and ``contains``. If ``compare`` is set to ``diff``, the number of lines of difference to allow (each line with a modification is a line added and a line removed so this counts as two lines).", + "title": "Lines Diff" + }, + "decompress": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/PermissiveBooleanValue" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If this attribute is true then try to decompress files if needed. This applies to\ntest assertions expressed with ``assert_contents`` or ``compare`` set to anything\nbut ``sim_size``.\nThis flag is useful for testing compressed outputs that are non-deterministic\ndespite having deterministic decompressed contents. By default, only files compressed\nwith bz2, gzip and zip will be automatically decompressed.\nNote, for specifying assertions for compressed as well as decompressed output\nthe corresponding output tag can be specified multiple times.\nThis is available in Galaxy since release 17.05 and was introduced in [pull request #3550](https://github.com/galaxyproject/galaxy/pull/3550).", + "title": "Decompress" + }, + "delta": { + "default": 10000, + "description": "If ``compare`` is set to ``sim_size``, this is the maximum allowed absolute size difference (in bytes) between the data set that is generated in the test and the file in ``test-data/`` that is referenced by the ``file`` attribute. Default value is 10000 bytes. Can be combined with ``delta_frac``.", + "title": "Delta", + "type": "integer" + }, + "delta_frac": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If ``compare`` is set to ``sim_size``, this is the maximum allowed relative size difference between the data set that is generated in the test and the file in ``test-data/`` that is referenced by the ``file`` attribute. A value of 0.1 means that the file that is generated in the test can differ by at most 10% of the file in ``test-data``. The default is not to check for relative size difference. Can be combined with ``delta``.", + "title": "Delta Frac" + }, + "count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Number or datasets for this output. Should be used for outputs with ``discover_datasets``", + "title": "Count" + }, + "location": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "URL that points to a remote output file that will downloaded and used for output comparison.\nPlease use this option only when is not possible to include the files in the `test-data` folder, since\nthis is more error prone due to external factors like remote availability.\nYou can use it in two ways:\n- In combination with `file` it will look for the output file in the `test-data` folder, if it's not available on disk it will\ndownload the file pointed by `location` using the same name as in `file` (or `value`).\n- Specifiying the `location` without a `file` (or `value`), it will download the file and use it as an alias of `file`. The name of the file\nwill be infered from the last component of the location URL. For example, `location=\"https://my_url/my_file.txt\"` will be equivalent to `file=\"my_file.txt\"`.\nIf you specify a `checksum`, it will be also used to check the integrity of the download.", + "title": "Location" + }, + "designation": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The designation of the discovered dataset.", + "title": "Designation" + } + }, + "title": "TestDiscoveredDataset", + "type": "object" + }, + "TestExtraFile": { + "additionalProperties": false, + "description": "Define test for extra files on corresponding output.", + "properties": { + "class": { + "anyOf": [ + { + "const": "File" + }, + { + "type": "null" + } + ], + "default": "File", + "title": "Class" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Path" + }, + "discovered_dataset": { + "items": { + "$ref": "#/$defs/TestDiscoveredDataset" + }, + "title": "Discovered Dataset", + "type": "array" + }, + "asserts": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/TestAssertions" + }, + "type": "array" + }, + { + "$ref": "#/$defs/TestAssertions" + }, + { + "type": "null" + } + ], + "default": null, + "description": "$assertions\n### Examples\nThe following demonstrates a wide variety of text-based and tabular\nassertion statements.\n```xml\n<output name=\"out_file1\">\n<assert_contents>\n<has_text text=\"chr7\" />\n<not_has_text text=\"chr8\" />\n<has_text_matching expression=\"1274\\d+53\" />\n<has_line_matching expression=\".*\\s+127489808\\s+127494553\" />\n<!-- &#009; is XML escape code for tab -->\n<has_line line=\"chr7&#009;127471195&#009;127489808\" />\n<has_n_columns n=\"3\" />\n</assert_contents>\n</output>\n```\nThe following demonstrates a wide variety of XML assertion statements.\n```xml\n<output name=\"out_file1\">\n<assert_contents>\n<is_valid_xml />\n<has_element_with_path path=\"BlastOutput_param/Parameters/Parameters_matrix\" />\n<has_n_elements_with_path n=\"9\" path=\"BlastOutput_iterations/Iteration/Iteration_hits/Hit/Hit_num\" />\n<element_text_matches path=\"BlastOutput_version\" expression=\"BLASTP\\s+2\\.2.*\" />\n<element_text_is path=\"BlastOutput_program\" text=\"blastp\" />\n<element_text path=\"BlastOutput_iterations/Iteration/Iteration_hits/Hit/Hit_def\">\n<not_has_text text=\"EDK72998.1\" />\n<has_text_matching expression=\"ABK[\\d\\.]+\" />\n</element_text>\n</assert_contents>\n</output>\n```\nThe following demonstrates verifying XML content with XPath-like expressions.\n```xml\n<output name=\"out_file1\">\n<assert_contents>\n<attribute_is path=\"outerElement/innerElement1\" attribute=\"foo\" text=\"bar\" />\n<attribute_matches path=\"outerElement/innerElement2\" attribute=\"foo2\" expression=\"bar\\d+\" />\n</assert_contents>\n</output>\n```", + "title": "Asserts" + }, + "extra_files": { + "items": { + "$ref": "#/$defs/TestExtraFile" + }, + "title": "Extra Files", + "type": "array" + }, + "metadata": { + "items": { + "$ref": "#/$defs/TestOutputMetadata" + }, + "title": "Metadata", + "type": "array" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "This value is the same as the value of the ``name`` attribute of the ``<data>``\ntag set contained within the tool's ``<outputs>`` tag set.", + "title": "Name" + }, + "file": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If specified, this value is the name of the output file stored in the target\n``test-data`` directory which will be used to compare the results of executing\nthe tool via the functional test framework.", + "title": "File" + }, + "value_json": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If specified, this value will be loaded as JSON and compared against the output\ngenerated as JSON. This can be useful for testing tool outputs that are not files.", + "title": "Value Json" + }, + "ftype": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If specified, this value will be checked against the corresponding output's\ndata type. If these do not match, the test will fail.", + "title": "Ftype" + }, + "sort": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/PermissiveBooleanValue" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Applies only if ``compare`` is ``diff``, ``re_match`` or ``re_match_multiline``. This flag causes the lines of the history data set to be sorted before the comparison. In case of ``diff`` and ``re_match`` also the local file is sorted. This could be\nuseful for non-deterministic output.", + "title": "Sort" + }, + "value": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "An alias for ``file``.", + "title": "Value" + }, + "md5": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If specified, the target output's MD5 hash should match the value specified\nhere. For large static files it may be inconvenient to upload the entiry file\nand this can be used instead.", + "title": "Md5" + }, + "checksum": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If specified, the target output's checksum should match the value specified\nhere. This value should have the form ``hash_type$hash_value``\n(e.g. ``sha1$8156d7ca0f46ed7abac98f82e36cfaddb2aca041``). For large static files\nit may be inconvenient to upload the entiry file and this can be used instead.", + "title": "Checksum" + }, + "compare": { + "anyOf": [ + { + "$ref": "#/$defs/TestOutputCompareType" + }, + { + "type": "null" + } + ], + "default": null + }, + "lines_diff": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Applies only if ``compare`` is set to ``diff``, ``re_match``, and ``contains``. If ``compare`` is set to ``diff``, the number of lines of difference to allow (each line with a modification is a line added and a line removed so this counts as two lines).", + "title": "Lines Diff" + }, + "decompress": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/PermissiveBooleanValue" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If this attribute is true then try to decompress files if needed. This applies to\ntest assertions expressed with ``assert_contents`` or ``compare`` set to anything\nbut ``sim_size``.\nThis flag is useful for testing compressed outputs that are non-deterministic\ndespite having deterministic decompressed contents. By default, only files compressed\nwith bz2, gzip and zip will be automatically decompressed.\nNote, for specifying assertions for compressed as well as decompressed output\nthe corresponding output tag can be specified multiple times.\nThis is available in Galaxy since release 17.05 and was introduced in [pull request #3550](https://github.com/galaxyproject/galaxy/pull/3550).", + "title": "Decompress" + }, + "delta": { + "default": 10000, + "description": "If ``compare`` is set to ``sim_size``, this is the maximum allowed absolute size difference (in bytes) between the data set that is generated in the test and the file in ``test-data/`` that is referenced by the ``file`` attribute. Default value is 10000 bytes. Can be combined with ``delta_frac``.", + "title": "Delta", + "type": "integer" + }, + "delta_frac": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If ``compare`` is set to ``sim_size``, this is the maximum allowed relative size difference between the data set that is generated in the test and the file in ``test-data/`` that is referenced by the ``file`` attribute. A value of 0.1 means that the file that is generated in the test can differ by at most 10% of the file in ``test-data``. The default is not to check for relative size difference. Can be combined with ``delta``.", + "title": "Delta Frac" + }, + "count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Number or datasets for this output. Should be used for outputs with ``discover_datasets``", + "title": "Count" + }, + "location": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "URL that points to a remote output file that will downloaded and used for output comparison.\nPlease use this option only when is not possible to include the files in the `test-data` folder, since\nthis is more error prone due to external factors like remote availability.\nYou can use it in two ways:\n- In combination with `file` it will look for the output file in the `test-data` folder, if it's not available on disk it will\ndownload the file pointed by `location` using the same name as in `file` (or `value`).\n- Specifiying the `location` without a `file` (or `value`), it will download the file and use it as an alias of `file`. The name of the file\nwill be infered from the last component of the location URL. For example, `location=\"https://my_url/my_file.txt\"` will be equivalent to `file=\"my_file.txt\"`.\nIf you specify a `checksum`, it will be also used to check the integrity of the download.", + "title": "Location" + }, + "type_value": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Extra file type (either ``file`` or ``directory``).", + "title": "Type Value" + } + }, + "title": "TestExtraFile", + "type": "object" + }, + "TestOutput": { + "additionalProperties": false, + "description": "This tag set defines the variable that names the output dataset for the\nfunctional test framework. The functional test framework will execute the tool\nusing the parameters defined in the ``<param>`` tag sets and generate a\ntemporary file, which will either be compared with the file named in the\n``file`` attribute value or checked against assertions made by a child\n``assert_contents`` tag to verify that the tool is functionally correct.\nDifferent methods can be chosen for the comparison with the local file\nspecified.\n\nby ``file`` using the ``compare`` attribute:\n- ``diff``: uses diff to compare the history data set and the file provided by\n``file``. Compressed files are decompressed before the compariopm if\n``decompress`` is set to ``true``. BAM files are converted to SAM before the\ncomparision and for pdf some special rules are implemented. The number of\nallowed differences can be set with ``lines_diff``. If ``sort=\"true\"`` history\nand local data is sorted before the comparison.\n- ``re_match``: each line of the history data set is compared to the regular\nexpression specified in the corresponding line of the ``file``. The allowed\nnumber of non matching lines can be set with ``lines_diff`` and the history\ndataset is sorted if ``sort`` is set to ``true``.\n- ``re_match_multiline``: it is checked if the history data sets matches the\nmulti line regular expression given in ``file``. The history dataset is sorted\nbefore the comparison if the ``sort`` atrribute is set to ``true``.\n- ``contains``: check if each line in ``file`` is contained in the history data set.\nThe allowed number of lines that are not contained in the history dataset\ncan be set with ``lines_diff``.\n- ``sim_size``: compares the size of the history dataset and the ``file`` subject to\nthe values of the ``delta`` and ``delta_frac`` attributes. Note that a ``has_size``\ncontent assertion should be preferred, because this avoids storing the test file.", + "properties": { + "class": { + "anyOf": [ + { + "const": "File" + }, + { + "type": "null" + } + ], + "default": "File", + "title": "Class" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Path" + }, + "discovered_dataset": { + "items": { + "$ref": "#/$defs/TestDiscoveredDataset" + }, + "title": "Discovered Dataset", + "type": "array" + }, + "asserts": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/TestAssertions" + }, + "type": "array" + }, + { + "$ref": "#/$defs/TestAssertions" + }, + { + "type": "null" + } + ], + "default": null, + "description": "$assertions\n### Examples\nThe following demonstrates a wide variety of text-based and tabular\nassertion statements.\n```xml\n<output name=\"out_file1\">\n<assert_contents>\n<has_text text=\"chr7\" />\n<not_has_text text=\"chr8\" />\n<has_text_matching expression=\"1274\\d+53\" />\n<has_line_matching expression=\".*\\s+127489808\\s+127494553\" />\n<!-- &#009; is XML escape code for tab -->\n<has_line line=\"chr7&#009;127471195&#009;127489808\" />\n<has_n_columns n=\"3\" />\n</assert_contents>\n</output>\n```\nThe following demonstrates a wide variety of XML assertion statements.\n```xml\n<output name=\"out_file1\">\n<assert_contents>\n<is_valid_xml />\n<has_element_with_path path=\"BlastOutput_param/Parameters/Parameters_matrix\" />\n<has_n_elements_with_path n=\"9\" path=\"BlastOutput_iterations/Iteration/Iteration_hits/Hit/Hit_num\" />\n<element_text_matches path=\"BlastOutput_version\" expression=\"BLASTP\\s+2\\.2.*\" />\n<element_text_is path=\"BlastOutput_program\" text=\"blastp\" />\n<element_text path=\"BlastOutput_iterations/Iteration/Iteration_hits/Hit/Hit_def\">\n<not_has_text text=\"EDK72998.1\" />\n<has_text_matching expression=\"ABK[\\d\\.]+\" />\n</element_text>\n</assert_contents>\n</output>\n```\nThe following demonstrates verifying XML content with XPath-like expressions.\n```xml\n<output name=\"out_file1\">\n<assert_contents>\n<attribute_is path=\"outerElement/innerElement1\" attribute=\"foo\" text=\"bar\" />\n<attribute_matches path=\"outerElement/innerElement2\" attribute=\"foo2\" expression=\"bar\\d+\" />\n</assert_contents>\n</output>\n```", + "title": "Asserts" + }, + "extra_files": { + "items": { + "$ref": "#/$defs/TestExtraFile" + }, + "title": "Extra Files", + "type": "array" + }, + "metadata": { + "items": { + "$ref": "#/$defs/TestOutputMetadata" + }, + "title": "Metadata", + "type": "array" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "This value is the same as the value of the ``name`` attribute of the ``<data>``\ntag set contained within the tool's ``<outputs>`` tag set.", + "title": "Name" + }, + "file": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If specified, this value is the name of the output file stored in the target\n``test-data`` directory which will be used to compare the results of executing\nthe tool via the functional test framework.", + "title": "File" + }, + "value_json": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If specified, this value will be loaded as JSON and compared against the output\ngenerated as JSON. This can be useful for testing tool outputs that are not files.", + "title": "Value Json" + }, + "ftype": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If specified, this value will be checked against the corresponding output's\ndata type. If these do not match, the test will fail.", + "title": "Ftype" + }, + "sort": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/PermissiveBooleanValue" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Applies only if ``compare`` is ``diff``, ``re_match`` or ``re_match_multiline``. This flag causes the lines of the history data set to be sorted before the comparison. In case of ``diff`` and ``re_match`` also the local file is sorted. This could be\nuseful for non-deterministic output.", + "title": "Sort" + }, + "value": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "An alias for ``file``.", + "title": "Value" + }, + "md5": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If specified, the target output's MD5 hash should match the value specified\nhere. For large static files it may be inconvenient to upload the entiry file\nand this can be used instead.", + "title": "Md5" + }, + "checksum": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If specified, the target output's checksum should match the value specified\nhere. This value should have the form ``hash_type$hash_value``\n(e.g. ``sha1$8156d7ca0f46ed7abac98f82e36cfaddb2aca041``). For large static files\nit may be inconvenient to upload the entiry file and this can be used instead.", + "title": "Checksum" + }, + "compare": { + "anyOf": [ + { + "$ref": "#/$defs/TestOutputCompareType" + }, + { + "type": "null" + } + ], + "default": null + }, + "lines_diff": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Applies only if ``compare`` is set to ``diff``, ``re_match``, and ``contains``. If ``compare`` is set to ``diff``, the number of lines of difference to allow (each line with a modification is a line added and a line removed so this counts as two lines).", + "title": "Lines Diff" + }, + "decompress": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/PermissiveBooleanValue" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If this attribute is true then try to decompress files if needed. This applies to\ntest assertions expressed with ``assert_contents`` or ``compare`` set to anything\nbut ``sim_size``.\nThis flag is useful for testing compressed outputs that are non-deterministic\ndespite having deterministic decompressed contents. By default, only files compressed\nwith bz2, gzip and zip will be automatically decompressed.\nNote, for specifying assertions for compressed as well as decompressed output\nthe corresponding output tag can be specified multiple times.\nThis is available in Galaxy since release 17.05 and was introduced in [pull request #3550](https://github.com/galaxyproject/galaxy/pull/3550).", + "title": "Decompress" + }, + "delta": { + "default": 10000, + "description": "If ``compare`` is set to ``sim_size``, this is the maximum allowed absolute size difference (in bytes) between the data set that is generated in the test and the file in ``test-data/`` that is referenced by the ``file`` attribute. Default value is 10000 bytes. Can be combined with ``delta_frac``.", + "title": "Delta", + "type": "integer" + }, + "delta_frac": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If ``compare`` is set to ``sim_size``, this is the maximum allowed relative size difference between the data set that is generated in the test and the file in ``test-data/`` that is referenced by the ``file`` attribute. A value of 0.1 means that the file that is generated in the test can differ by at most 10% of the file in ``test-data``. The default is not to check for relative size difference. Can be combined with ``delta``.", + "title": "Delta Frac" + }, + "count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Number or datasets for this output. Should be used for outputs with ``discover_datasets``", + "title": "Count" + }, + "location": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "URL that points to a remote output file that will downloaded and used for output comparison.\nPlease use this option only when is not possible to include the files in the `test-data` folder, since\nthis is more error prone due to external factors like remote availability.\nYou can use it in two ways:\n- In combination with `file` it will look for the output file in the `test-data` folder, if it's not available on disk it will\ndownload the file pointed by `location` using the same name as in `file` (or `value`).\n- Specifiying the `location` without a `file` (or `value`), it will download the file and use it as an alias of `file`. The name of the file\nwill be infered from the last component of the location URL. For example, `location=\"https://my_url/my_file.txt\"` will be equivalent to `file=\"my_file.txt\"`.\nIf you specify a `checksum`, it will be also used to check the integrity of the download.", + "title": "Location" + } + }, + "title": "TestOutput", + "type": "object" + }, + "TestOutputCollection": { + "additionalProperties": false, + "properties": { + "class": { + "anyOf": [ + { + "const": "Collection" + }, + { + "type": "null" + } + ], + "default": "Collection", + "title": "Class" + }, + "element": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/TestOutput" + }, + "type": "array" + }, + { + "$ref": "#/$defs/TestOutput" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Element" + }, + "count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Number of elements in output collection.", + "title": "Count" + } + }, + "title": "TestOutputCollection", + "type": "object" + }, + "TestOutputCollectionDeprecated": { + "additionalProperties": false, + "properties": { + "element_tests": { + "additionalProperties": { + "anyOf": [ + { + "$ref": "#/$defs/TestOutputElement" + }, + { + "$ref": "#/$defs/TestOutput" + } + ] + }, + "description": "Deprecated field, please use elements to describe expectations about collection elements.", + "metadata": { + "deprecated": true + }, + "title": "Element Tests", + "type": "object" + }, + "collection_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Collection Type" + }, + "class": { + "anyOf": [ + { + "const": "Collection" + }, + { + "type": "null" + } + ], + "default": "Collection", + "title": "Class" + }, + "element": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/TestOutput" + }, + "type": "array" + }, + { + "$ref": "#/$defs/TestOutput" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Element" + }, + "count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Number of elements in output collection.", + "title": "Count" + } + }, + "required": [ + "element_tests" + ], + "title": "TestOutputCollectionDeprecated", + "type": "object" + }, + "TestOutputCompareType": { + "description": "Type of comparison to use when comparing test generated output files to\nexpected output files.\n\nCurrently valid value are\n``diff`` (the default), ``re_match``, ``re_match_multiline``,\nand ``contains``. In addition there is ``sim_size`` which is discouraged in favour of a ``has_size`` assertion.", + "enum": [ + "diff", + "re_match", + "sim_size", + "re_match_multiline", + "contains" + ], + "title": "TestOutputCompareType", + "type": "string" + }, + "TestOutputElement": { + "additionalProperties": false, + "properties": { + "elements": { + "additionalProperties": { + "anyOf": [ + { + "$ref": "#/$defs/TestOutputElement" + }, + { + "$ref": "#/$defs/TestOutput" + } + ] + }, + "title": "Elements", + "type": "object" + }, + "class": { + "anyOf": [ + { + "const": "File" + }, + { + "type": "null" + } + ], + "default": "File", + "title": "Class" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Path" + }, + "discovered_dataset": { + "items": { + "$ref": "#/$defs/TestDiscoveredDataset" + }, + "title": "Discovered Dataset", + "type": "array" + }, + "asserts": { + "anyOf": [ + { + "items": { + "$ref": "#/$defs/TestAssertions" + }, + "type": "array" + }, + { + "$ref": "#/$defs/TestAssertions" + }, + { + "type": "null" + } + ], + "default": null, + "description": "$assertions\n### Examples\nThe following demonstrates a wide variety of text-based and tabular\nassertion statements.\n```xml\n<output name=\"out_file1\">\n<assert_contents>\n<has_text text=\"chr7\" />\n<not_has_text text=\"chr8\" />\n<has_text_matching expression=\"1274\\d+53\" />\n<has_line_matching expression=\".*\\s+127489808\\s+127494553\" />\n<!-- &#009; is XML escape code for tab -->\n<has_line line=\"chr7&#009;127471195&#009;127489808\" />\n<has_n_columns n=\"3\" />\n</assert_contents>\n</output>\n```\nThe following demonstrates a wide variety of XML assertion statements.\n```xml\n<output name=\"out_file1\">\n<assert_contents>\n<is_valid_xml />\n<has_element_with_path path=\"BlastOutput_param/Parameters/Parameters_matrix\" />\n<has_n_elements_with_path n=\"9\" path=\"BlastOutput_iterations/Iteration/Iteration_hits/Hit/Hit_num\" />\n<element_text_matches path=\"BlastOutput_version\" expression=\"BLASTP\\s+2\\.2.*\" />\n<element_text_is path=\"BlastOutput_program\" text=\"blastp\" />\n<element_text path=\"BlastOutput_iterations/Iteration/Iteration_hits/Hit/Hit_def\">\n<not_has_text text=\"EDK72998.1\" />\n<has_text_matching expression=\"ABK[\\d\\.]+\" />\n</element_text>\n</assert_contents>\n</output>\n```\nThe following demonstrates verifying XML content with XPath-like expressions.\n```xml\n<output name=\"out_file1\">\n<assert_contents>\n<attribute_is path=\"outerElement/innerElement1\" attribute=\"foo\" text=\"bar\" />\n<attribute_matches path=\"outerElement/innerElement2\" attribute=\"foo2\" expression=\"bar\\d+\" />\n</assert_contents>\n</output>\n```", + "title": "Asserts" + }, + "extra_files": { + "items": { + "$ref": "#/$defs/TestExtraFile" + }, + "title": "Extra Files", + "type": "array" + }, + "metadata": { + "items": { + "$ref": "#/$defs/TestOutputMetadata" + }, + "title": "Metadata", + "type": "array" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "This value is the same as the value of the ``name`` attribute of the ``<data>``\ntag set contained within the tool's ``<outputs>`` tag set.", + "title": "Name" + }, + "file": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If specified, this value is the name of the output file stored in the target\n``test-data`` directory which will be used to compare the results of executing\nthe tool via the functional test framework.", + "title": "File" + }, + "value_json": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If specified, this value will be loaded as JSON and compared against the output\ngenerated as JSON. This can be useful for testing tool outputs that are not files.", + "title": "Value Json" + }, + "ftype": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If specified, this value will be checked against the corresponding output's\ndata type. If these do not match, the test will fail.", + "title": "Ftype" + }, + "sort": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/PermissiveBooleanValue" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Applies only if ``compare`` is ``diff``, ``re_match`` or ``re_match_multiline``. This flag causes the lines of the history data set to be sorted before the comparison. In case of ``diff`` and ``re_match`` also the local file is sorted. This could be\nuseful for non-deterministic output.", + "title": "Sort" + }, + "value": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "An alias for ``file``.", + "title": "Value" + }, + "md5": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If specified, the target output's MD5 hash should match the value specified\nhere. For large static files it may be inconvenient to upload the entiry file\nand this can be used instead.", + "title": "Md5" + }, + "checksum": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If specified, the target output's checksum should match the value specified\nhere. This value should have the form ``hash_type$hash_value``\n(e.g. ``sha1$8156d7ca0f46ed7abac98f82e36cfaddb2aca041``). For large static files\nit may be inconvenient to upload the entiry file and this can be used instead.", + "title": "Checksum" + }, + "compare": { + "anyOf": [ + { + "$ref": "#/$defs/TestOutputCompareType" + }, + { + "type": "null" + } + ], + "default": null + }, + "lines_diff": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Applies only if ``compare`` is set to ``diff``, ``re_match``, and ``contains``. If ``compare`` is set to ``diff``, the number of lines of difference to allow (each line with a modification is a line added and a line removed so this counts as two lines).", + "title": "Lines Diff" + }, + "decompress": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/PermissiveBooleanValue" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If this attribute is true then try to decompress files if needed. This applies to\ntest assertions expressed with ``assert_contents`` or ``compare`` set to anything\nbut ``sim_size``.\nThis flag is useful for testing compressed outputs that are non-deterministic\ndespite having deterministic decompressed contents. By default, only files compressed\nwith bz2, gzip and zip will be automatically decompressed.\nNote, for specifying assertions for compressed as well as decompressed output\nthe corresponding output tag can be specified multiple times.\nThis is available in Galaxy since release 17.05 and was introduced in [pull request #3550](https://github.com/galaxyproject/galaxy/pull/3550).", + "title": "Decompress" + }, + "delta": { + "default": 10000, + "description": "If ``compare`` is set to ``sim_size``, this is the maximum allowed absolute size difference (in bytes) between the data set that is generated in the test and the file in ``test-data/`` that is referenced by the ``file`` attribute. Default value is 10000 bytes. Can be combined with ``delta_frac``.", + "title": "Delta", + "type": "integer" + }, + "delta_frac": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If ``compare`` is set to ``sim_size``, this is the maximum allowed relative size difference between the data set that is generated in the test and the file in ``test-data/`` that is referenced by the ``file`` attribute. A value of 0.1 means that the file that is generated in the test can differ by at most 10% of the file in ``test-data``. The default is not to check for relative size difference. Can be combined with ``delta``.", + "title": "Delta Frac" + }, + "count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Number or datasets for this output. Should be used for outputs with ``discover_datasets``", + "title": "Count" + }, + "location": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "URL that points to a remote output file that will downloaded and used for output comparison.\nPlease use this option only when is not possible to include the files in the `test-data` folder, since\nthis is more error prone due to external factors like remote availability.\nYou can use it in two ways:\n- In combination with `file` it will look for the output file in the `test-data` folder, if it's not available on disk it will\ndownload the file pointed by `location` using the same name as in `file` (or `value`).\n- Specifiying the `location` without a `file` (or `value`), it will download the file and use it as an alias of `file`. The name of the file\nwill be infered from the last component of the location URL. For example, `location=\"https://my_url/my_file.txt\"` will be equivalent to `file=\"my_file.txt\"`.\nIf you specify a `checksum`, it will be also used to check the integrity of the download.", + "title": "Location" + } + }, + "required": [ + "elements" + ], + "title": "TestOutputElement", + "type": "object" + }, + "TestOutputMetadata": { + "additionalProperties": false, + "description": "This directive specifies a test for an output's metadata as an expected key-\nvalue pair.\n\n### Example\nThe functional test tool\n[tool_provided_metadata_1.xml](https://github.com/galaxyproject/galaxy/blob/dev/test/functional/tools/tool_provided_metadata_1.xml)\nprovides a demonstration of using this tag.\n```xml\n<test>\n<param name=\"input1\" value=\"simple_line.txt\" />\n<output name=\"out1\" file=\"simple_line.txt\" ftype=\"txt\">\n<metadata name=\"name\" value=\"my dynamic name\" />\n<metadata name=\"info\" value=\"my dynamic info\" />\n<metadata name=\"dbkey\" value=\"cust1\" />\n</output>\n</test>\n```", + "properties": { + "name": { + "description": "Name of the metadata element to check.", + "title": "Name", + "type": "string" + }, + "value": { + "description": "Expected value (as a string) of metadata value.", + "title": "Value", + "type": "string" + } + }, + "required": [ + "name", + "value" + ], + "title": "TestOutputMetadata", + "type": "object" + } + }, + "items": { + "$ref": "#/$defs/Test" + }, + "title": "ListOfTests", + "type": "array" +} diff --git a/planemo/schema/validate_schema.py b/planemo/schema/validate_schema.py new file mode 100644 index 000000000..8137598e8 --- /dev/null +++ b/planemo/schema/validate_schema.py @@ -0,0 +1,24 @@ +import pathlib +import subprocess +import sys +from typing import ( + List, + Optional, +) + +SCHEMA = pathlib.Path(__file__).parent / "test_file_schema.json" + + +def validate_schema(test_files: List[str], verbose: bool = False) -> Optional[str]: + """ + Runs check_jsonschema on `test_files`. + + Returns validation failure message if validation failed. + """ + check_args = [sys.executable, "-m", "check_jsonschema", "--schemafile", str(SCHEMA), *test_files] + if verbose: + check_args.append("--verbose") + result = subprocess.run(check_args, capture_output=True, text=True) + if result.returncode: + return result.stdout + return None diff --git a/planemo/workflow_lint.py b/planemo/workflow_lint.py index b10a9e450..913038140 100644 --- a/planemo/workflow_lint.py +++ b/planemo/workflow_lint.py @@ -39,10 +39,12 @@ required_input_labels, ) from planemo.runnable import ( + _tests_path, cases, for_path, TestCase, ) +from planemo.schema.validate_schema import validate_schema from planemo.shed import DOCKSTORE_REGISTRY_CONF if TYPE_CHECKING: @@ -52,6 +54,7 @@ DOCKSTORE_REGISTRY_CONF_VERSION = "1.2" MAIN_TOOLSHED_URL = "https://toolshed.g2.bx.psu.edu" +INPUT_STEP_TYPES = {"data_input", "data_collection_input", "parameter_input"} class WorkflowLintContext(LintContext): @@ -172,6 +175,12 @@ def _lint_tsts(path: str, lint_context: WorkflowLintContext) -> None: lint_context.warn("Workflow missing test cases.") return all_tests_valid = True + test_paths = _tests_path(runnable=runnable) + if test_paths: + validation_errors = validate_schema(test_files=[test_paths]) + if validation_errors: + lint_context.error(validation_errors) + all_tests_valid = False for test_case in test_cases: if isinstance(test_case, TestCase): if not _lint_case(path, test_case, lint_context): @@ -205,6 +214,8 @@ def check_json_for_untyped_params(j): workflow_dict = ordered_load(f) steps = workflow_dict.get("steps", {}) + if isinstance(steps, dict): + steps = steps.values() # annotation if not workflow_dict.get("annotation"): @@ -219,11 +230,12 @@ def check_json_for_untyped_params(j): lint_context.warn("Workflow does not specify a license.") # checks on individual steps - for step in steps.values(): - print(step) + for step in steps: # disconnected inputs for input in step.get("inputs", []): - if input.get("name") not in step.get("input_connections"): # TODO: check optional + if step.get("type") not in INPUT_STEP_TYPES and input.get("name") not in step.get( + "input_connections" + ): # TODO: check optional lint_context.warn( f"Input {input.get('name')} of workflow step {step.get('annotation') or step.get('id')} is disconnected." ) @@ -260,8 +272,7 @@ def _lint_case(path: str, test_case: TestCase, lint_context: WorkflowLintContext job_keys = test_case.input_ids for key in job_keys: if key not in i_labels: - # consider an error instead? - lint_context.warn( + lint_context.error( f"Unknown workflow input in test job definition [{key}], workflow inputs are [{i_labels}]" ) test_valid = False @@ -301,13 +312,14 @@ def _lint_case(path: str, test_case: TestCase, lint_context: WorkflowLintContext def is_valid_output_expectations(lint_context, output_expectations): all_assertion_definitions = [] + element_tests = output_expectations.get("element_tests") or output_expectations.get("elements") if isinstance(output_expectations, (int, str, float, bool)): # CWL style parameter output return True - elif "element_tests" in output_expectations: + elif element_tests: # This is a collection - for element_id in output_expectations["element_tests"]: - all_assertion_definitions.append(output_expectations["element_tests"][element_id].get("asserts")) + for element_id in element_tests: + all_assertion_definitions.append(element_tests[element_id].get("asserts")) else: all_assertion_definitions.append(output_expectations.get("asserts")) for assertion_definitions in all_assertion_definitions: @@ -486,7 +498,9 @@ def _lint_tool_ids_steps(lint_context: WorkflowLintContext, wf_dict: Dict, ts: T """Returns whether a single tool_id was invalid""" failed = False steps = wf_dict.get("steps", {}) - for step in steps.values(): + if isinstance(steps, dict): + steps = steps.values() + for step in steps: if step.get("type", "tool") == "tool" and not step.get("run", {}).get("class") == "GalaxyWorkflow": warning_msg, _ = find_repos_from_tool_id(step["tool_id"], ts) if warning_msg != "": diff --git a/requirements.txt b/requirements.txt index 080f8f932..92dc2c90e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,16 +3,17 @@ bioblend>=1.0.0 click!=8.0.2 cwltool>=1.0.20191225192155 ephemeris>=0.10.3 -galaxy-tool-util>=23.0,<24.0 -galaxy-util[template]>=23.0,<24.0 +galaxy-tool-util>=23.2.dev0,<24.0 +galaxy-util[template]>=23.2.dev0,<24.0 glob2 gxformat2>=0.14.0 h5py jinja2 +check-jsonschema lxml oyaml pathvalidate pyyaml virtualenv stdlib_list; python_version < '3.10' -tabulate \ No newline at end of file +tabulate diff --git a/setup.py b/setup.py index 7401ca058..b2589319a 100644 --- a/setup.py +++ b/setup.py @@ -56,6 +56,7 @@ def get_var(var_name): "planemo.galaxy.test", "planemo.linters", "planemo.reports", + "planemo.schema", "planemo.shed", "planemo.shed2tap", "planemo.test", diff --git a/tests/data/wf16_optional_input_output_label-test.yml b/tests/data/wf16_optional_input_output_label-test.yml index d38c242c1..c1836c274 100644 --- a/tests/data/wf16_optional_input_output_label-test.yml +++ b/tests/data/wf16_optional_input_output_label-test.yml @@ -1,2 +1,3 @@ - doc: Test optional input workflow output job: {} + outputs: {} diff --git a/tests/data/wf7-collection-output-fail.gxwf-test.yml b/tests/data/wf7-collection-output-fail.gxwf-test.yml index c369545db..053417f31 100644 --- a/tests/data/wf7-collection-output-fail.gxwf-test.yml +++ b/tests/data/wf7-collection-output-fail.gxwf-test.yml @@ -9,8 +9,7 @@ path: hello.txt outputs: wf_output_1: - attributes: {} - element_tests: + elements: el1: elements: forward: diff --git a/tests/data/wf7-collection-output.gxwf-test.yml b/tests/data/wf7-collection-output.gxwf-test.yml index 2dd7337b2..d3ed2f497 100644 --- a/tests/data/wf7-collection-output.gxwf-test.yml +++ b/tests/data/wf7-collection-output.gxwf-test.yml @@ -9,7 +9,6 @@ path: hello.txt outputs: wf_output_1: - attributes: {} element_tests: el1: elements: diff --git a/tests/data/wf_repos/basic_format2_collection_wrong_assert/basic_format2.gxwf-test.yml b/tests/data/wf_repos/basic_format2_collection_wrong_assert/basic_format2.gxwf-test.yml index df45b7277..29f0c0425 100644 --- a/tests/data/wf_repos/basic_format2_collection_wrong_assert/basic_format2.gxwf-test.yml +++ b/tests/data/wf_repos/basic_format2_collection_wrong_assert/basic_format2.gxwf-test.yml @@ -21,10 +21,10 @@ text: Word second: asserts: - - that: has_text - text: Hello - - that: has_text - text: World - - that: not_has_text - text: Word + - has_text: + text: Hello + - has_text: + text: World + - not_has_text: + text: Word diff --git a/tests/data/wf_repos/basic_format2_collection_wrong_assert_list/basic_format2.gxwf-test.yml b/tests/data/wf_repos/basic_format2_collection_wrong_assert_list/basic_format2.gxwf-test.yml index 002c62989..ffcb1bd1f 100644 --- a/tests/data/wf_repos/basic_format2_collection_wrong_assert_list/basic_format2.gxwf-test.yml +++ b/tests/data/wf_repos/basic_format2_collection_wrong_assert_list/basic_format2.gxwf-test.yml @@ -21,10 +21,10 @@ text: Word second: asserts: - - that: has_text - text: Hello - - that: has_line - text: Hello World! - - that: not_has_text - text: Word + - has_text: + text: Hello + - has_line: + text: Hello World! + - not_has_text: + text: Word diff --git a/tests/data/wf_repos/basic_format2_ok_collection/basic_format2.gxwf-test.yml b/tests/data/wf_repos/basic_format2_ok_collection/basic_format2.gxwf-test.yml index 229c96471..675c11d09 100644 --- a/tests/data/wf_repos/basic_format2_ok_collection/basic_format2.gxwf-test.yml +++ b/tests/data/wf_repos/basic_format2_ok_collection/basic_format2.gxwf-test.yml @@ -21,10 +21,10 @@ text: Word second: asserts: - - that: has_text - text: Hello - - that: has_text - text: World - - that: not_has_text - text: Word + - has_text: + text: Hello + - has_text: + text: World + - not_has_text: + text: Word diff --git a/tests/data/wf_repos/basic_format2_ok_list/basic_format2.gxwf-test.yml b/tests/data/wf_repos/basic_format2_ok_list/basic_format2.gxwf-test.yml index 69392f66b..9703bc254 100644 --- a/tests/data/wf_repos/basic_format2_ok_list/basic_format2.gxwf-test.yml +++ b/tests/data/wf_repos/basic_format2_ok_list/basic_format2.gxwf-test.yml @@ -6,9 +6,9 @@ outputs: the_output: asserts: - - that: has_text - text: Hello - - that: has_text - text: World - - that: not_has_text - text: Word + - has_text: + text: Hello + - has_text: + text: World + - not_has_text: + text: Word diff --git a/tests/data/wf_repos/basic_format2_wrong_assert_list/basic_format2.gxwf-test.yml b/tests/data/wf_repos/basic_format2_wrong_assert_list/basic_format2.gxwf-test.yml index 5921fdf10..5ff93994a 100644 --- a/tests/data/wf_repos/basic_format2_wrong_assert_list/basic_format2.gxwf-test.yml +++ b/tests/data/wf_repos/basic_format2_wrong_assert_list/basic_format2.gxwf-test.yml @@ -6,9 +6,9 @@ outputs: the_output: asserts: - - that: has_text - text: Hello - - that: has_text - line: Hello World! - - that: not_has_text - text: Word + - has_text: + text: Hello + - has_text: + line: Hello World! + - not_has_text: + text: Word