Skip to content

Commit

Permalink
has_size assertion: implement size (as synonym for value)
Browse files Browse the repository at this point in the history
  • Loading branch information
bernt-matthias committed Feb 18, 2024
1 parent 85ba4d5 commit fc1d21d
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 16 deletions.
31 changes: 29 additions & 2 deletions lib/galaxy/tool_util/linters/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,33 @@ def lint(cls, tool_source: "ToolSource", lint_ctx: "LintContext"):


class TestsAssertsHasSizeQuant(Linter):
"""
has_size needs at least one of size (or value), min, max
"""
@classmethod
def lint(cls, tool_source: "ToolSource", lint_ctx: "LintContext"):
tool_xml = getattr(tool_source, "xml_tree", None)
if not tool_xml:
return
tests = tool_xml.findall("./tests/test")
for test_idx, test in enumerate(tests, start=1):
for a in test.xpath(
".//*[self::assert_contents or self::assert_stdout or self::assert_stderr or self::assert_command]//*"
):
if a.tag != "has_size":
continue
if len(set(a.attrib) & set(["value", "size", "min", "max"])) == 0:
lint_ctx.error(
f"Test {test_idx}: '{a.tag}' needs to specify 'size', 'min', or 'max'",
linter=cls.name(),
node=a,
)


class TestsAssertsHasSizeOrValueQuant(Linter):
"""
has_size should not have size and value
"""
@classmethod
def lint(cls, tool_source: "ToolSource", lint_ctx: "LintContext"):
tool_xml = getattr(tool_source, "xml_tree", None)
Expand All @@ -97,9 +124,9 @@ def lint(cls, tool_source: "ToolSource", lint_ctx: "LintContext"):
):
if a.tag != "has_size":
continue
if len(set(a.attrib) & set(["value", "min", "max"])) == 0:
if "value" in a.attrib and "size" in a.attrib:
lint_ctx.error(
f"Test {test_idx}: '{a.tag}' needs to specify 'value', 'min', or 'max'",
f"Test {test_idx}: '{a.tag}' must not specify 'value' and 'size'",
linter=cls.name(),
node=a,
)
Expand Down
6 changes: 5 additions & 1 deletion lib/galaxy/tool_util/verify/asserts/size.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,20 @@
def assert_has_size(
output_bytes: bytes,
value: Optional[Union[int, str]] = None,
size: Optional[Union[int, str]] = None,
delta: Union[int, str] = 0,
min: Optional[Union[int, str]] = None,
max: Optional[Union[int, str]] = None,
negate: Union[bool, str] = False,
) -> None:
"""
Asserts the specified output has a size of the specified value,
Asserts the specified output has a size of the specified value
(size and value or synonyms),
allowing for absolute (delta) and relative (delta_frac) difference.
"""
output_size = len(output_bytes)
if size is None:
size = value
_assert_number(
output_size,
value,
Expand Down
7 changes: 6 additions & 1 deletion lib/galaxy/tool_util/xsd/galaxy.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -2251,11 +2251,16 @@ $attribute_list::5
]]>
</xs:documentation>
</xs:annotation>
<xs:attribute name="value" type="Bytes" use="optional">
<xs:attribute name="size" type="Bytes" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">Desired size of the output (in bytes), can be suffixed by ``(k|M|G|T|P|E)i?``</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="value" type="Bytes" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">An outdated synonym for `size`</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="delta" type="Bytes" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">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?``</xs:documentation>
Expand Down
8 changes: 5 additions & 3 deletions test/unit/tool_util/test_tool_linters.py
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,7 @@
<invalid/>
</assert_stderr>
<assert_command>
<has_size value="500k" size="50"/>
<has_text invalid_attrib="blah"/>
</assert_command>
<output name="out_archive">
Expand Down Expand Up @@ -1799,11 +1800,12 @@ def test_tests_asserts(lint_ctx):
"Invalid XML: Element 'not_has_text', attribute 'invalid_attrib_also_checked_in_nested_asserts': The attribute 'invalid_attrib_also_checked_in_nested_asserts' is not allowed."
in lint_ctx.error_messages
)
assert "Test 1: 'has_size' needs to specify 'value', 'min', or 'max'" in lint_ctx.error_messages
assert "Test 1: 'has_size' needs to specify 'size', 'min', or 'max'" in lint_ctx.error_messages
assert "Test 1: 'has_size' must not specify 'value' and 'size'" in lint_ctx.error_messages
assert "Test 1: 'has_n_columns' needs to specify 'n', 'min', or 'max'" in lint_ctx.error_messages
assert "Test 1: 'has_n_lines' needs to specify 'n', 'min', or 'max'" in lint_ctx.error_messages
assert not lint_ctx.warn_messages
assert len(lint_ctx.error_messages) == 8
assert len(lint_ctx.error_messages) == 9


def test_tests_output_type_mismatch(lint_ctx):
Expand Down Expand Up @@ -2076,7 +2078,7 @@ def test_xml_comments_are_ignored(lint_ctx: LintContext):
def test_list_linters():
linter_names = Linter.list_listers()
# make sure to add/remove a test for new/removed linters if this number changes
assert len(linter_names) == 129
assert len(linter_names) == 130
assert "Linter" not in linter_names
# make sure that linters from all modules are available
for prefix in [
Expand Down
18 changes: 9 additions & 9 deletions test/unit/tool_util/verify/test_asserts.py
Original file line number Diff line number Diff line change
Expand Up @@ -472,12 +472,12 @@ def test_has_line_matching_n_failure():

SIZE_HAS_SIZE_ASSERTION = """
<assert_contents>
<has_size value="{value}"/>
<has_size {size_attrib}="{value}"/>
</assert_contents>
"""
SIZE_HAS_SIZE_ASSERTION_DELTA = """
<assert_contents>
<has_size value="{value}" delta="{delta}"/>
<has_size {size_attrib}="{value}" delta="{delta}"/>
</assert_contents>
"""

Expand All @@ -491,39 +491,39 @@ def test_has_line_matching_n_failure():

def test_has_size_success():
"""test has_size"""
a = run_assertions(SIZE_HAS_SIZE_ASSERTION.format(value=10), TEXT_DATA_HAS_TEXT)
a = run_assertions(SIZE_HAS_SIZE_ASSERTION.format(size_attrib="size", value=10), TEXT_DATA_HAS_TEXT)
assert len(a) == 0


def test_has_size_failure():
"""test has_size .. negative test"""
a = run_assertions(SIZE_HAS_SIZE_ASSERTION.format(value="10"), TEXT_DATA_HAS_TEXT * 2)
a = run_assertions(SIZE_HAS_SIZE_ASSERTION.format(size_attrib="value", value="10"), TEXT_DATA_HAS_TEXT * 2)
assert "Expected file size of 10+-0 found 20" in a
assert len(a) == 1


def test_has_size_delta():
"""test has_size .. delta"""
a = run_assertions(SIZE_HAS_SIZE_ASSERTION_DELTA.format(value="10", delta="10"), TEXT_DATA_HAS_TEXT * 2)
a = run_assertions(SIZE_HAS_SIZE_ASSERTION_DELTA.format(size_attrib="size", value="10", delta="10"), TEXT_DATA_HAS_TEXT * 2)
assert len(a) == 0


def test_has_size_with_bytes_suffix():
"""test has_size .. bytes suffix"""
a = run_assertions(SIZE_HAS_SIZE_ASSERTION_DELTA.format(value="1k", delta="0"), TEXT_DATA_HAS_TEXT * 100)
a = run_assertions(SIZE_HAS_SIZE_ASSERTION_DELTA.format(size_attrib="size", value="1k", delta="0"), TEXT_DATA_HAS_TEXT * 100)
assert len(a) == 0


def test_has_size_with_bytes_suffix_failure():
"""test has_size .. bytes suffix .. negative"""
a = run_assertions(SIZE_HAS_SIZE_ASSERTION_DELTA.format(value="1Mi", delta="10k"), TEXT_DATA_HAS_TEXT * 100)
a = run_assertions(SIZE_HAS_SIZE_ASSERTION_DELTA.format(size_attrib="value", value="1Mi", delta="10k"), TEXT_DATA_HAS_TEXT * 100)
assert "Expected file size of 1Mi+-10k found 1000" in a
assert len(a) == 1


def test_has_size_decompress_gz():
"""test has_size with gzipped data using decompress=True (which in real life is set int he parent output tag)"""
a = run_assertions(SIZE_HAS_SIZE_ASSERTION.format(value="100"), GZA100, decompress=True)
a = run_assertions(SIZE_HAS_SIZE_ASSERTION.format(size_attrib="size", value="100"), GZA100, decompress=True)
assert len(a) == 0


Expand All @@ -532,7 +532,7 @@ def test_has_size_decompress_txt():
test has_size with NON-gzipped data using decompress=True
-> decompress should be ignored - in particular there should be no error
"""
a = run_assertions(SIZE_HAS_SIZE_ASSERTION.format(value="100"), A100, decompress=True)
a = run_assertions(SIZE_HAS_SIZE_ASSERTION.format(size_attrib="size", value="100"), A100, decompress=True)
assert len(a) == 0


Expand Down

0 comments on commit fc1d21d

Please sign in to comment.