From ce56ebc3adad33e46566c1effb1c35c781283fd9 Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Wed, 30 Nov 2022 12:08:26 +0100 Subject: [PATCH 1/6] decompress history data for testing assertions currently (text) test assertions are not applicable to compressed data. with this test data will be decompressed befor testing content assertions if the decopress keyword is given in the parent `output` or `element`. --- lib/galaxy/tool_util/verify/__init__.py | 2 +- lib/galaxy/tool_util/verify/asserts/__init__.py | 11 ++++++++++- lib/galaxy/tool_util/xsd/galaxy.xsd | 8 +++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/lib/galaxy/tool_util/verify/__init__.py b/lib/galaxy/tool_util/verify/__init__.py index 990c11d4f79f..4c11e1dddbbb 100644 --- a/lib/galaxy/tool_util/verify/__init__.py +++ b/lib/galaxy/tool_util/verify/__init__.py @@ -73,7 +73,7 @@ def _retrieve_file_content(filename: str) -> bytes: assertions = attributes.get("assert_list", None) if attributes is not None and assertions is not None: try: - verify_assertions(output_content, attributes["assert_list"]) + verify_assertions(output_content, attributes["assert_list"], attributes.get("decompress")) except AssertionError as err: errmsg = f"{item_label} different than expected\n" errmsg += unicodify(err) diff --git a/lib/galaxy/tool_util/verify/asserts/__init__.py b/lib/galaxy/tool_util/verify/asserts/__init__.py index f37bc018e095..f6ef206fb99c 100644 --- a/lib/galaxy/tool_util/verify/asserts/__init__.py +++ b/lib/galaxy/tool_util/verify/asserts/__init__.py @@ -4,8 +4,10 @@ getfullargspec, getmembers, ) +from tempfile import NamedTemporaryFile from galaxy.util import unicodify +from galaxy.util.compression_utils import get_fileobj log = logging.getLogger(__name__) @@ -30,9 +32,16 @@ assertion_functions[member] = value -def verify_assertions(data: bytes, assertion_description_list): +def verify_assertions(data: bytes, assertion_description_list, decompress=None): """This function takes a list of assertions and a string to check these assertions against.""" + if decompress: + with NamedTemporaryFile(delete=False) as tmpfh: + tmpfh.write(data) + tmpfh.close() + with get_fileobj(tmpfh.name, compressed_formats=None) as fh: + data = fh.read() + for assertion_description in assertion_description_list: verify_assertion(data, assertion_description) diff --git a/lib/galaxy/tool_util/xsd/galaxy.xsd b/lib/galaxy/tool_util/xsd/galaxy.xsd index c110c081d24b..86e0038a3423 100644 --- a/lib/galaxy/tool_util/xsd/galaxy.xsd +++ b/lib/galaxy/tool_util/xsd/galaxy.xsd @@ -1724,7 +1724,13 @@ it may be inconvenient to upload the entiry file and this can be used instead. From 9ccc101f3ef16a13a936349ca84b4aeb4494d491 Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Thu, 15 Dec 2022 16:52:29 +0100 Subject: [PATCH 2/6] restructure as suggested --- lib/galaxy/tool_util/verify/asserts/__init__.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/galaxy/tool_util/verify/asserts/__init__.py b/lib/galaxy/tool_util/verify/asserts/__init__.py index f6ef206fb99c..5da05a01a579 100644 --- a/lib/galaxy/tool_util/verify/asserts/__init__.py +++ b/lib/galaxy/tool_util/verify/asserts/__init__.py @@ -36,12 +36,11 @@ def verify_assertions(data: bytes, assertion_description_list, decompress=None): """This function takes a list of assertions and a string to check these assertions against.""" if decompress: - with NamedTemporaryFile(delete=False) as tmpfh: + with NamedTemporaryFile() as tmpfh: tmpfh.write(data) - tmpfh.close() - with get_fileobj(tmpfh.name, compressed_formats=None) as fh: - data = fh.read() - + tmpfh.flush() + with get_fileobj(tmpfh.name, mode="rb", compressed_formats=None) as fh: + data = fh.read() for assertion_description in assertion_description_list: verify_assertion(data, assertion_description) From 41772f6effc4dc99cb88fddce7526d254a627030 Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Thu, 15 Dec 2022 16:52:41 +0100 Subject: [PATCH 3/6] rewrite assertion unit tests --- test/unit/tool_util/verify/test_asserts.py | 1623 +++++++++++--------- 1 file changed, 921 insertions(+), 702 deletions(-) diff --git a/test/unit/tool_util/verify/test_asserts.py b/test/unit/tool_util/verify/test_asserts.py index a6519e57f706..e98f345d4719 100644 --- a/test/unit/tool_util/verify/test_asserts.py +++ b/test/unit/tool_util/verify/test_asserts.py @@ -6,7 +6,6 @@ import h5py except ImportError: h5py = None -import pytest from galaxy.tool_util.parser.xml import __parse_assert_list_from_elem from galaxy.tool_util.verify import asserts @@ -42,6 +41,44 @@ 1\t2\t3 """ + +def test_has_n_columns_success(): + """test successful assertion""" + a = run_assertions(TABULAR_ASSERTION, TABULAR_DATA_POS) + assert len(a) == 0 + + +def test_has_n_columns_failure(): + """test wrong number of columns""" + a = run_assertions(TABULAR_ASSERTION, TABULAR_DATA_NEG) + assert "Expected 3+-0 columns in output found 4" in a + assert len(a) == 1 + + +def test_has_n_columns_for_csv(): + """test wrong number of columns for csv data""" + a = run_assertions(TABULAR_CSV_ASSERTION, TABULAR_CSV_DATA) + assert "Expected the number of columns in output to be in [3:inf] found 2" in a + assert len(a) == 1 + + +def test_has_n_columns_with_comments(): + """test tabular data with comments""" + a = run_assertions(TABULAR_ASSERTION_COMMENT, TABULAR_DATA_COMMENT) + assert len(a) == 0 + + +TEXT_DATA_HAS_TEXT = """test text +""" + +TEXT_DATA_HAS_TEXT_NEG = """desired content +is not here +""" + +TEXT_DATA_NONE = None + +TEXT_DATA_EMPTY = "" + TEXT_HAS_TEXT_ASSERTION = """ @@ -96,6 +133,167 @@ """ + +def test_has_text_success(): + """test has_text""" + a = run_assertions(TEXT_HAS_TEXT_ASSERTION, TEXT_DATA_HAS_TEXT) + assert len(a) == 0 + + +def test_has_text_failure(): + """test has_text .. negative test""" + a = run_assertions(TEXT_HAS_TEXT_ASSERTION, TEXT_DATA_HAS_TEXT_NEG) + assert "Expected text 'test text' in output ('desired content\nis not here\n')" in a + assert len(a) == 1 + + +def test_has_text_None_output(): + """test has_text with None output""" + a = run_assertions(TEXT_HAS_TEXT_ASSERTION, TEXT_DATA_NONE) + assert "Checking has_text assertion on empty output (None)" in a + assert len(a) == 1 + + +def test_has_text_empty_output(): + """test has_text with empty output""" + a = run_assertions(TEXT_HAS_TEXT_ASSERTION, TEXT_DATA_EMPTY) + assert "Expected text 'test text' in output ('')" in a + assert len(a) == 1 + + +def test_has_text_n_success(): + """test has_text with n""" + a = run_assertions(TEXT_HAS_TEXT_ASSERTION_N, TEXT_DATA_HAS_TEXT * 2) + assert len(a) == 0 + + +def test_has_text_n_failure(): + """test has_text with n .. negative test""" + a = run_assertions(TEXT_HAS_TEXT_ASSERTION_N, TEXT_DATA_HAS_TEXT) + assert "Expected 2+-0 occurences of 'test text' in output ('test text\n') found 1" in a + assert len(a) == 1 + + +def test_has_text_n_delta_success(): + """test has_text with n and delta""" + a = run_assertions(TEXT_HAS_TEXT_ASSERTION_N_DELTA, TEXT_DATA_HAS_TEXT * 2) + assert len(a) == 0 + + +def test_has_text_n_delta_failure(): + """test has_text with n and delta .. negative test""" + a = run_assertions(TEXT_HAS_TEXT_ASSERTION_N_DELTA, TEXT_DATA_HAS_TEXT) + assert "Expected 3+-1 occurences of 'test text' in output ('test text\n') found 1" in a + assert len(a) == 1 + + +def test_has_text_minmax_delta_success(): + """test has_text with min max""" + a = run_assertions(TEXT_HAS_TEXT_ASSERTION_MIN_MAX, TEXT_DATA_HAS_TEXT * 2) + assert len(a) == 0 + + +def test_has_text_minmax_delta_failure(): + """test has_text with min max .. negative test""" + a = run_assertions(TEXT_HAS_TEXT_ASSERTION_MIN_MAX, TEXT_DATA_HAS_TEXT) + assert "Expected that the number of occurences of 'test text' in output is in [2:4] ('test text\n') found 1" in a + assert len(a) == 1 + + +def test_has_text_negate_success(): + """test has_text negate""" + a = run_assertions(TEXT_HAS_TEXT_ASSERTION_NEGATE, TEXT_DATA_HAS_TEXT_NEG) + assert len(a) == 0 + + +def test_has_text_negate_failure(): + """test has_text negate .. negative test""" + a = run_assertions(TEXT_HAS_TEXT_ASSERTION_NEGATE, TEXT_DATA_HAS_TEXT) + assert "Did not expect text 'test text' in output ('test text\n')" in a + assert len(a) == 1 + + +def test_has_text_negate_None_output(): + """test has_text negate with None output .. should have the same output as with negate='false'""" + a = run_assertions(TEXT_HAS_TEXT_ASSERTION_NEGATE, TEXT_DATA_NONE) + assert "Checking has_text assertion on empty output (None)" in a + assert len(a) == 1 + + +def test_has_text_negate_empty_output(): + """test has_text negate with empty output""" + a = run_assertions(TEXT_HAS_TEXT_ASSERTION_NEGATE, TEXT_DATA_EMPTY) + assert len(a) == 0 + + +def test_has_text_negate_n_success(): + """test has_text negate with n""" + a = run_assertions(TEXT_HAS_TEXT_ASSERTION_N_NEGATE, TEXT_DATA_HAS_TEXT) + assert len(a) == 0 + + +def test_has_text_negate_n_failure(): + """test has_text negate with n .. negative test""" + a = run_assertions(TEXT_HAS_TEXT_ASSERTION_N_NEGATE, TEXT_DATA_HAS_TEXT * 2) + assert "Did not expect 2+-0 occurences of 'test text' in output ('test text\ntest text\n') found 2" in a + assert len(a) == 1 + + +def test_has_text_negate_n_delta_success(): + """test has_text negate with n and delta""" + a = run_assertions(TEXT_HAS_TEXT_ASSERTION_N_DELTA_NEGATE, TEXT_DATA_HAS_TEXT) + assert len(a) == 0 + + +def test_has_text_negate_n_delta_failure(): + """test has_text negate with n and delta .. negative test""" + a = run_assertions(TEXT_HAS_TEXT_ASSERTION_N_DELTA_NEGATE, TEXT_DATA_HAS_TEXT * 2) + assert "Did not expect 3+-1 occurences of 'test text' in output ('test text\ntest text\n') found 2" in a + assert len(a) == 1 + + +def test_has_text_negate_minmax_delta_success(): + """test has_text negate with min max""" + a = run_assertions(TEXT_HAS_TEXT_ASSERTION_MIN_MAX_NEGATE, TEXT_DATA_HAS_TEXT) + assert len(a) == 0 + + +def test_has_text_negate_minmax_delta_failure(): + """test has_text negate with min max .. negative test""" + a = run_assertions(TEXT_HAS_TEXT_ASSERTION_MIN_MAX_NEGATE, TEXT_DATA_HAS_TEXT * 2) + assert ( + "Did not expect that the number of occurences of 'test text' in output is in [2:4] ('test text\ntest text\n') found 2" + in a + ) + assert len(a) == 1 + + +def test_not_has_text_success(): + """test not_has_text""" + a = run_assertions(TEXT_NOT_HAS_TEXT_ASSERTION, TEXT_DATA_HAS_TEXT) + assert len(a) == 0 + + +def test_not_has_text_failure(): + """test not_has_text .. negative test""" + a = run_assertions(TEXT_NOT_HAS_TEXT_ASSERTION, TEXT_DATA_HAS_TEXT_NEG) + assert "Output file contains unexpected text 'not here'" in a + assert len(a) == 1 + + +def test_not_has_text_None_output(): + """test not_has_text with None output""" + a = run_assertions(TEXT_NOT_HAS_TEXT_ASSERTION, TEXT_DATA_NONE) + assert "Checking not_has_text assertion on empty output (None)" in a + assert len(a) == 1 + + +def test_not_has_text_empty_output(): + """test not_has_text with empty output""" + a = run_assertions(TEXT_NOT_HAS_TEXT_ASSERTION, TEXT_DATA_EMPTY) + assert len(a) == 0 + + TEXT_HAS_TEXT_MATCHING_ASSERTION = """ @@ -114,6 +312,49 @@ """ + +def test_has_text_matching_success(): + """test has_text_matching""" + a = run_assertions(TEXT_HAS_TEXT_MATCHING_ASSERTION, TEXT_DATA_HAS_TEXT) + assert len(a) == 0 + + +def test_has_text_matching_failure(): + """test has_text_matching .. negative test""" + a = run_assertions(TEXT_HAS_TEXT_MATCHING_ASSERTION, TEXT_DATA_HAS_TEXT_NEG) + assert "Expected text matching expression 'te[sx]t' in output ('desired content\nis not here\n')" in a + assert len(a) == 1 + + +def test_has_text_matching_n_success(): + """test has_text_matching with n""" + a = run_assertions(TEXT_HAS_TEXT_MATCHING_ASSERTION_N, TEXT_DATA_HAS_TEXT * 2) + assert len(a) == 0 + + +def test_has_text_matching_n_failure(): + """test has_text_matching with n .. negative test (using the test text where "te[sx]st" appears twice)""" + a = run_assertions(TEXT_HAS_TEXT_MATCHING_ASSERTION_N, TEXT_DATA_HAS_TEXT) + assert "Expected 4+-0 (non-overlapping) matches for 'te[sx]t' in output ('test text\n') found 2" in a + assert len(a) == 1 + + +def test_has_text_matching_minmax_success(): + """test has_text_matching with min/max""" + a = run_assertions(TEXT_HAS_TEXT_MATCHING_ASSERTION_MINMAX, TEXT_DATA_HAS_TEXT * 2) + assert len(a) == 0 + + +def test_has_text_matching_minmax_failure(): + """test has_text_matching with n .. negative test (using the test text where "te[sx]st" appears twice)""" + a = run_assertions(TEXT_HAS_TEXT_MATCHING_ASSERTION_MINMAX, TEXT_DATA_HAS_TEXT) + assert ( + "Expected that the number of (non-overlapping) matches for 'te[sx]t' in output is in [3:5] ('test text\n') found 2" + in a + ) + assert len(a) == 1 + + TEXT_HAS_LINE_ASSERTION = """ @@ -145,6 +386,88 @@ """ + +def test_has_line_success(): + """test has_line""" + a = run_assertions(TEXT_HAS_LINE_ASSERTION, TEXT_DATA_HAS_TEXT) + assert len(a) == 0 + + +def test_has_line_failure(): + """test has_line .. negative test""" + a = run_assertions(TEXT_HAS_LINE_ASSERTION, TEXT_DATA_HAS_TEXT_NEG) + assert "Expected line 'test text' in output ('desired content\nis not here\n')" in a + assert len(a) == 1 + + +def test_has_line_n_success(): + """test has_line with n""" + a = run_assertions(TEXT_HAS_LINE_ASSERTION_N, TEXT_DATA_HAS_TEXT * 2) + assert len(a) == 0 + + +def test_has_line_n_failure(): + """test has_line with n .. negative test""" + a = run_assertions(TEXT_HAS_LINE_ASSERTION_N, TEXT_DATA_HAS_TEXT) + assert "Expected 2+-0 lines 'test text' in output ('test text\n') found 1" in a + assert len(a) == 1 + + +def test_has_n_lines_success(): + """test has_n_lines""" + a = run_assertions(TEXT_HAS_N_LINES_ASSERTION.format(n="2"), TEXT_DATA_HAS_TEXT * 2) + assert len(a) == 0 + + +def test_has_n_lines_n_as_bytes_success(): + """test has_n_lines .. bytes""" + a = run_assertions(TEXT_HAS_N_LINES_ASSERTION.format(n="2ki"), TEXT_DATA_HAS_TEXT * 2048) + assert len(a) == 0 + + +def test_has_n_lines_failure(): + """test has_n_lines .. negative test""" + a = run_assertions( + TEXT_HAS_N_LINES_ASSERTION.format(n="2"), + TEXT_DATA_HAS_TEXT, + ) + assert "Expected 2+-0 lines in the output found 1" in a + assert len(a) == 1 + + +def test_has_n_lines_delta(): + """test has_n_lines ..delta""" + a = run_assertions(TEXT_HAS_N_LINES_ASSERTION_DELTA.format(n="3", delta="1"), TEXT_DATA_HAS_TEXT) + assert "Expected 3+-1 lines in the output found 1" in a + assert len(a) == 1 + + +def test_has_line_matching_success(): + """test has_line_matching""" + a = run_assertions(TEXT_HAS_LINE_MATCHING_ASSERTION, TEXT_DATA_HAS_TEXT) + assert len(a) == 0 + + +def test_has_line_matching_failure(): + """test has_line_matching .. negative test""" + a = run_assertions(TEXT_HAS_LINE_MATCHING_ASSERTION, TEXT_DATA_HAS_TEXT_NEG) + assert "Expected line matching expression 'te[sx]t te[sx]t' in output ('desired content\nis not here\n')" in a + assert len(a) == 1 + + +def test_has_line_matching_n_success(): + """test has_line_matching n""" + a = run_assertions(TEXT_HAS_LINE_MATCHING_ASSERTION_N, TEXT_DATA_HAS_TEXT * 2) + assert len(a) == 0 + + +def test_has_line_matching_n_failure(): + """test has_line_matching n .. negative test""" + a = run_assertions(TEXT_HAS_LINE_MATCHING_ASSERTION_N, TEXT_DATA_HAS_TEXT) + assert "Expected 2+-0 lines matching for 'te[sx]t te[sx]t' in output ('test text\n') found 1" in a + assert len(a) == 1 + + SIZE_HAS_SIZE_ASSERTION = """ @@ -156,23 +479,73 @@ """ -TEXT_DATA_HAS_TEXT = """test text -""" -TEXT_DATA_HAS_TEXT_NEG = """desired content -is not here -""" +def test_has_size_success(): + """test has_size""" + a = run_assertions(SIZE_HAS_SIZE_ASSERTION.format(value=10), TEXT_DATA_HAS_TEXT) + assert len(a) == 0 -TEXT_DATA_NONE = None -TEXT_DATA_EMPTY = "" +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) + 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) + 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) + 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) + assert "Expected file size of 1Mi+-10k found 1000" in a + assert len(a) == 1 + +VALID_XML = """ + + BAR + BAZ + QUX + + + +""" + +INVALID_XML = '' XML_IS_VALID_XML_ASSERTION = """ """ + + +def test_is_valid_xml_success(): + """test is_valid_xml""" + a = run_assertions(XML_IS_VALID_XML_ASSERTION, VALID_XML) + assert len(a) == 0 + + +def test_is_valid_xml_failure(): + """test is_valid_xml .. negative test""" + a = run_assertions(XML_IS_VALID_XML_ASSERTION, INVALID_XML) + assert ( + "Expected valid XML, but could not parse output. Opening and ending tag mismatch: elem line 1 and root, line 1, column 31 (, line 1)" + in a + ) + + XML_HAS_ELEMENT_WITH_PATH = """ @@ -216,419 +589,164 @@ """ -JSON_HAS_PROPERTY_WITH_VALUE = """ - - - -""" -JSON_HAS_PROPERTY_WITH_WITH = """ - - - -""" +def test_has_element_with_path_success_1(): + """test has_element_with_path""" + a = run_assertions(XML_HAS_ELEMENT_WITH_PATH.format(path="./elem[1]/more"), VALID_XML) + assert len(a) == 0 -VALID_XML = """ - - BAR - BAZ - QUX - - - -""" -INVALID_XML = '' -VALID_SIMPLE_JSON = """{"foo": 5, "list": [{"textprop": "right"}]}""" +def test_has_element_with_path_success_2(): + """test has_element_with_path""" + a = run_assertions(XML_HAS_ELEMENT_WITH_PATH.format(path="./elem[@name='foo']"), VALID_XML) + assert len(a) == 0 -if h5py is not None: - with tempfile.NamedTemporaryFile(delete=False) as tmp: - h5name = tmp.name - with h5py.File(tmp.name, "w") as h5fh: - h5fh.attrs["myfileattr"] = "myfileattrvalue" - h5fh.attrs["myfileattrint"] = 1 - dset = h5fh.create_dataset("myint", (100,), dtype="i") - dset.attrs["myintattr"] = "myintattrvalue" - grp = h5fh.create_group("mygroup") - grp.attrs["mygroupattr"] = "mygroupattrvalue" - grp.create_dataset("myfloat", (50,), dtype="f") - dset.attrs["myfloatattr"] = "myfloatattrvalue" - with open(h5name, "rb") as h5fh: - H5BYTES = h5fh.read() - os.remove(h5name) +def test_has_element_with_path_success_3(): + """test has_element_with_path""" + a = run_assertions(XML_HAS_ELEMENT_WITH_PATH.format(path=".//more[@name]"), VALID_XML) + assert len(a) == 0 - H5_HAS_H5_KEYS = """ - - - - """ - H5_HAS_H5_KEYS_NEGATIVE = """ - - - - """ - H5_HAS_ATTRIBUTE = """ - - - - - """ - H5_HAS_ATTRIBUTE_NEGATIVE = """ - - - - - """ -# create a test directory structure for zipping -# might also be done directly with the fipfile/tarfile module without creating -# a tmpdir, but its much harder to create empty directories or symlinks -tmpdir = tempfile.mkdtemp() -for f in ["file1.txt", "testdir/file1.txt", "testdir/file2.txt", "testdir/dir2/file1.txt"]: - tmpfile = os.path.join(tmpdir, f) - os.makedirs(os.path.dirname(tmpfile), exist_ok=True) - with open(tmpfile, "w") as fh: - fh.write(f) -os.makedirs(os.path.join(tmpdir, "emptydir")) -os.symlink("testdir/file1.txt", os.path.join(tmpdir, "symlink")) +def test_has_element_with_path_failure(): + """test has_element_with_path .. negative test""" + a = run_assertions(XML_HAS_ELEMENT_WITH_PATH.format(path="./blah"), VALID_XML) + assert "Expected path './blah' in xml" in a -with tempfile.NamedTemporaryFile(suffix=".zip", delete=False) as ziptmp: - zipname = ziptmp.name - shutil.make_archive(zipname[:-4], "zip", tmpdir) - with open(zipname, "rb") as zfh: - ZIPBYTES = zfh.read() -with tempfile.NamedTemporaryFile(suffix=".tar.gz", delete=False) as ziptmp: - zipname = ziptmp.name - shutil.make_archive(zipname[:-7], "gztar", tmpdir) - with open(zipname, "rb") as zfh: - TARBYTES = zfh.read() -shutil.rmtree(tmpdir) +def test_has_n_elements_with_path_success_1(): + """test has_n_elements_with_path""" + a = run_assertions(XML_HAS_N_ELEMENTS_WITH_PATH.format(path="./elem", n="2"), VALID_XML) + assert len(a) == 0 -with tempfile.NamedTemporaryFile(mode="w", delete=False) as nonarchivetmp: - nonarchivename = nonarchivetmp.name - nonarchivetmp.write("some text") -with open(nonarchivename, "rb") as ntmp: - NONARCHIVE = ntmp.read() -ARCHIVE_HAS_ARCHIVE_MEMBER = """ - - - {content_assert} - - -""" +def test_has_n_elements_with_path_success_2(): + """test has_n_elements_with_path""" + a = run_assertions(XML_HAS_N_ELEMENTS_WITH_PATH.format(path="./elem[1]/more", n="3"), VALID_XML) + assert len(a) == 0 -ARCHIVE_HAS_ARCHIVE_MEMBER_N = """ - - - {content_assert} - - -""" -ARCHIVE_HAS_ARCHIVE_MEMBER_MINMAX = """ - - - {content_assert} - - -""" +def test_has_n_elements_with_path_success_3(): + """test has_n_elements_with_path""" + a = run_assertions(XML_HAS_N_ELEMENTS_WITH_PATH.format(path="./elem[@name='foo']/more", n="3"), VALID_XML) + assert len(a) == 0 -TESTS = [ - # test successful assertion - (TABULAR_ASSERTION, TABULAR_DATA_POS, lambda x: len(x) == 0), - # test wrong number of columns - (TABULAR_ASSERTION, TABULAR_DATA_NEG, lambda x: "Expected 3+-0 columns in output found 4" in x), - # test wrong number of columns for csv data - ( - TABULAR_CSV_ASSERTION, - TABULAR_CSV_DATA, - lambda x: "Expected the number of columns in output to be in [3:inf] found 2" in x, - ), - # test tabular data with comments - (TABULAR_ASSERTION_COMMENT, TABULAR_DATA_COMMENT, lambda x: len(x) == 0), - # test has_text - (TEXT_HAS_TEXT_ASSERTION, TEXT_DATA_HAS_TEXT, lambda x: len(x) == 0), - # test has_text .. negative test - ( - TEXT_HAS_TEXT_ASSERTION, - TEXT_DATA_HAS_TEXT_NEG, - lambda x: "Expected text 'test text' in output ('desired content\nis not here\n')" in x, - ), - # test has_text with None output - (TEXT_HAS_TEXT_ASSERTION, TEXT_DATA_NONE, lambda x: "Checking has_text assertion on empty output (None)" in x), - # test has_text with empty output - (TEXT_HAS_TEXT_ASSERTION, TEXT_DATA_EMPTY, lambda x: "Expected text 'test text' in output ('')" in x), - # test has_text with n - (TEXT_HAS_TEXT_ASSERTION_N, TEXT_DATA_HAS_TEXT * 2, lambda x: len(x) == 0), - # test has_text with n .. negative test - ( - TEXT_HAS_TEXT_ASSERTION_N, - TEXT_DATA_HAS_TEXT, - lambda x: "Expected 2+-0 occurences of 'test text' in output ('test text\n') found 1" in x, - ), - # test has_text with n and delta - (TEXT_HAS_TEXT_ASSERTION_N_DELTA, TEXT_DATA_HAS_TEXT * 2, lambda x: len(x) == 0), - # test has_text with n and delta .. negative test - ( - TEXT_HAS_TEXT_ASSERTION_N_DELTA, - TEXT_DATA_HAS_TEXT, - lambda x: "Expected 3+-1 occurences of 'test text' in output ('test text\n') found 1" in x, - ), - # test has_text with min max - (TEXT_HAS_TEXT_ASSERTION_MIN_MAX, TEXT_DATA_HAS_TEXT * 2, lambda x: len(x) == 0), - # test has_text with min max .. negative test - ( - TEXT_HAS_TEXT_ASSERTION_MIN_MAX, - TEXT_DATA_HAS_TEXT, - lambda x: "Expected that the number of occurences of 'test text' in output is in [2:4] ('test text\n') found 1" - in x, - ), - # test has_text negate - (TEXT_HAS_TEXT_ASSERTION_NEGATE, TEXT_DATA_HAS_TEXT_NEG, lambda x: len(x) == 0), - # test has_text negate .. negative test - ( - TEXT_HAS_TEXT_ASSERTION_NEGATE, - TEXT_DATA_HAS_TEXT, - lambda x: "Did not expect text 'test text' in output ('test text\n')" in x, - ), - # test has_text negate with None output .. should have the same output as with negate="false" - ( - TEXT_HAS_TEXT_ASSERTION_NEGATE, - TEXT_DATA_NONE, - lambda x: "Checking has_text assertion on empty output (None)" in x, - ), - # test has_text negate with empty output - (TEXT_HAS_TEXT_ASSERTION_NEGATE, TEXT_DATA_EMPTY, lambda x: len(x) == 0), - # test has_text negate with n - (TEXT_HAS_TEXT_ASSERTION_N_NEGATE, TEXT_DATA_HAS_TEXT, lambda x: len(x) == 0), - # test has_text negate with n .. negative test - ( - TEXT_HAS_TEXT_ASSERTION_N_NEGATE, - TEXT_DATA_HAS_TEXT * 2, - lambda x: "Did not expect 2+-0 occurences of 'test text' in output ('test text\ntest text\n') found 2" in x, - ), - # test has_text negate with n and delta - (TEXT_HAS_TEXT_ASSERTION_N_DELTA_NEGATE, TEXT_DATA_HAS_TEXT, lambda x: len(x) == 0), - # test has_text negate with n and delta .. negative test - ( - TEXT_HAS_TEXT_ASSERTION_N_DELTA_NEGATE, - TEXT_DATA_HAS_TEXT * 2, - lambda x: "Did not expect 3+-1 occurences of 'test text' in output ('test text\ntest text\n') found 2" in x, - ), - # test has_text negate with min max - (TEXT_HAS_TEXT_ASSERTION_MIN_MAX_NEGATE, TEXT_DATA_HAS_TEXT, lambda x: len(x) == 0), - # test has_text negate with min max .. negative test - ( - TEXT_HAS_TEXT_ASSERTION_MIN_MAX_NEGATE, - TEXT_DATA_HAS_TEXT * 2, - lambda x: "Did not expect that the number of occurences of 'test text' in output is in [2:4] ('test text\ntest text\n') found 2" - in x, - ), - # test not_has_text - (TEXT_NOT_HAS_TEXT_ASSERTION, TEXT_DATA_HAS_TEXT, lambda x: len(x) == 0), - # test not_has_text .. negative test - ( - TEXT_NOT_HAS_TEXT_ASSERTION, - TEXT_DATA_HAS_TEXT_NEG, - lambda x: "Output file contains unexpected text 'not here'" in x, - ), - # test not_has_text with None output - ( - TEXT_NOT_HAS_TEXT_ASSERTION, - TEXT_DATA_NONE, - lambda x: "Checking not_has_text assertion on empty output (None)" in x, - ), - # test not_has_text with empty output - (TEXT_NOT_HAS_TEXT_ASSERTION, TEXT_DATA_EMPTY, lambda x: len(x) == 0), - # test has_text_matching - (TEXT_HAS_TEXT_MATCHING_ASSERTION, TEXT_DATA_HAS_TEXT, lambda x: len(x) == 0), - # test has_text_matching .. negative test - ( - TEXT_HAS_TEXT_MATCHING_ASSERTION, - TEXT_DATA_HAS_TEXT_NEG, - lambda x: "Expected text matching expression 'te[sx]t' in output ('desired content\nis not here\n')" in x, - ), - # test has_text_matching with n - (TEXT_HAS_TEXT_MATCHING_ASSERTION_N, TEXT_DATA_HAS_TEXT * 2, lambda x: len(x) == 0), - # test has_text_matching with n .. negative test (using the test text where "te[sx]st" appears twice) - ( - TEXT_HAS_TEXT_MATCHING_ASSERTION_N, - TEXT_DATA_HAS_TEXT, - lambda x: "Expected 4+-0 (non-overlapping) matches for 'te[sx]t' in output ('test text\n') found 2" in x, - ), - # test has_text_matching with n - (TEXT_HAS_TEXT_MATCHING_ASSERTION_MINMAX, TEXT_DATA_HAS_TEXT * 2, lambda x: len(x) == 0), - # test has_text_matching with n .. negative test (using the test text where "te[sx]st" appears twice) - ( - TEXT_HAS_TEXT_MATCHING_ASSERTION_MINMAX, - TEXT_DATA_HAS_TEXT, - lambda x: "Expected that the number of (non-overlapping) matches for 'te[sx]t' in output is in [3:5] ('test text\n') found 2" - in x, - ), - # test has_line - (TEXT_HAS_LINE_ASSERTION, TEXT_DATA_HAS_TEXT, lambda x: len(x) == 0), - # test has_line .. negative test - ( - TEXT_HAS_LINE_ASSERTION, - TEXT_DATA_HAS_TEXT_NEG, - lambda x: "Expected line 'test text' in output ('desired content\nis not here\n')" in x, - ), - # test has_line with n - (TEXT_HAS_LINE_ASSERTION_N, TEXT_DATA_HAS_TEXT * 2, lambda x: len(x) == 0), - # test has_line with n .. negative test - ( - TEXT_HAS_LINE_ASSERTION_N, - TEXT_DATA_HAS_TEXT, - lambda x: "Expected 2+-0 lines 'test text' in output ('test text\n') found 1" in x, - ), - # test has_n_lines - (TEXT_HAS_N_LINES_ASSERTION.format(n="2"), TEXT_DATA_HAS_TEXT * 2, lambda x: len(x) == 0), - # test has_n_lines .. bytes - (TEXT_HAS_N_LINES_ASSERTION.format(n="2ki"), TEXT_DATA_HAS_TEXT * 2048, lambda x: len(x) == 0), - # test has_n_lines .. negative test - ( - TEXT_HAS_N_LINES_ASSERTION.format(n="2"), - TEXT_DATA_HAS_TEXT, - lambda x: "Expected 2+-0 lines in the output found 1" in x, - ), - # test has_n_lines ..delta - ( - TEXT_HAS_N_LINES_ASSERTION_DELTA.format(n="3", delta="1"), - TEXT_DATA_HAS_TEXT, - lambda x: "Expected 3+-1 lines in the output found 1" in x, - ), - # test has_line_matching - (TEXT_HAS_LINE_MATCHING_ASSERTION, TEXT_DATA_HAS_TEXT, lambda x: len(x) == 0), - # test has_line_matching .. negative test - ( - TEXT_HAS_LINE_MATCHING_ASSERTION, - TEXT_DATA_HAS_TEXT_NEG, - lambda x: "Expected line matching expression 'te[sx]t te[sx]t' in output ('desired content\nis not here\n')" - in x, - ), - # test has_line_matching n - (TEXT_HAS_LINE_MATCHING_ASSERTION_N, TEXT_DATA_HAS_TEXT * 2, lambda x: len(x) == 0), - # test has_line_matching n .. negative test - ( - TEXT_HAS_LINE_MATCHING_ASSERTION_N, - TEXT_DATA_HAS_TEXT, - lambda x: "Expected 2+-0 lines matching for 'te[sx]t te[sx]t' in output ('test text\n') found 1" in x, - ), - # test has_size - (SIZE_HAS_SIZE_ASSERTION.format(value=10), TEXT_DATA_HAS_TEXT, lambda x: len(x) == 0), - # test has_size .. negative test - ( - SIZE_HAS_SIZE_ASSERTION.format(value="10"), - TEXT_DATA_HAS_TEXT * 2, - lambda x: "Expected file size of 10+-0 found 20" in x, - ), - # test has_size .. delta - (SIZE_HAS_SIZE_ASSERTION_DELTA.format(value="10", delta="10"), TEXT_DATA_HAS_TEXT * 2, lambda x: len(x) == 0), - # test has_size .. bytes suffix - (SIZE_HAS_SIZE_ASSERTION_DELTA.format(value="1k", delta="0"), TEXT_DATA_HAS_TEXT * 100, lambda x: len(x) == 0), - # test has_size .. bytes suffix .. negative - ( - SIZE_HAS_SIZE_ASSERTION_DELTA.format(value="1Mi", delta="10k"), - TEXT_DATA_HAS_TEXT * 100, - lambda x: "Expected file size of 1Mi+-10k found 1000" in x, - ), - # test is_valid_xml - (XML_IS_VALID_XML_ASSERTION, VALID_XML, lambda x: len(x) == 0), - # test is_valid_xml .. negative test - ( - XML_IS_VALID_XML_ASSERTION, - INVALID_XML, - lambda x: "Expected valid XML, but could not parse output. Opening and ending tag mismatch: elem line 1 and root, line 1, column 31 (, line 1)" - in x, - ), - # test has_element_with_path - (XML_HAS_ELEMENT_WITH_PATH.format(path="./elem[1]/more"), VALID_XML, lambda x: len(x) == 0), - (XML_HAS_ELEMENT_WITH_PATH.format(path="./elem[@name='foo']"), VALID_XML, lambda x: len(x) == 0), - (XML_HAS_ELEMENT_WITH_PATH.format(path=".//more[@name]"), VALID_XML, lambda x: len(x) == 0), - # test has_element_with_path .. negative test - (XML_HAS_ELEMENT_WITH_PATH.format(path="./blah"), VALID_XML, lambda x: "Expected path './blah' in xml" in x), - # test has_n_elements_with_path - (XML_HAS_N_ELEMENTS_WITH_PATH.format(path="./elem", n="2"), VALID_XML, lambda x: len(x) == 0), - # test has_n_elements_with_path - (XML_HAS_N_ELEMENTS_WITH_PATH.format(path="./elem[1]/more", n="3"), VALID_XML, lambda x: len(x) == 0), - # test has_n_elements_with_path - (XML_HAS_N_ELEMENTS_WITH_PATH.format(path="./elem[@name='foo']/more", n="3"), VALID_XML, lambda x: len(x) == 0), - # test has_n_elements_with_path - (XML_HAS_N_ELEMENTS_WITH_PATH.format(path="./elem[2]/more", n="0"), VALID_XML, lambda x: len(x) == 0), - # test has_n_elements_with_path .. negative test - ( - XML_HAS_N_ELEMENTS_WITH_PATH.format(path="./elem", n="1"), - VALID_XML, - lambda x: "Expected 1+-0 occurrences of path './elem' in xml found 2" in x, - ), - # test element_text_matches - (XML_ELEMENT_TEXT_MATCHES.format(path="./elem/more", expression="BA(R|Z)"), VALID_XML, lambda x: len(x) == 0), - # test element_text_matches more specific path - (XML_ELEMENT_TEXT_MATCHES.format(path="./elem/more[2]", expression="BA(R|Z)"), VALID_XML, lambda x: len(x) == 0), - # test element_text_matches .. negative test - ( + +def test_has_n_elements_with_path_success_4(): + """test has_n_elements_with_path""" + a = run_assertions(XML_HAS_N_ELEMENTS_WITH_PATH.format(path="./elem[2]/more", n="0"), VALID_XML) + assert len(a) == 0 + + +def test_has_n_elements_with_path_failure(): + """test has_n_elements_with_path .. negative test""" + a = run_assertions(XML_HAS_N_ELEMENTS_WITH_PATH.format(path="./elem", n="1"), VALID_XML) + assert "Expected 1+-0 occurrences of path './elem' in xml found 2" in a + assert len(a) == 1 + + +def test_element_text_matches_sucess(): + """test element_text_matches""" + a = run_assertions(XML_ELEMENT_TEXT_MATCHES.format(path="./elem/more", expression="BA(R|Z)"), VALID_XML) + assert len(a) == 0 + + +def test_element_text_matches_sucess_with_more_specific_path(): + """test element_text_matches more specific path""" + a = run_assertions(XML_ELEMENT_TEXT_MATCHES.format(path="./elem/more[2]", expression="BA(R|Z)"), VALID_XML) + assert len(a) == 0 + + +def test_element_text_matches_failure(): + """test element_text_matches .. negative test""" + a = run_assertions( XML_ELEMENT_TEXT_MATCHES.format(path="./elem/more", expression="QU(X|Y)"), VALID_XML, - lambda x: "Text of element with path './elem/more': Expected text matching expression 'QU(X|Y)' in output ('BAR')" - in x, - ), - # test element_text_is - (XML_ELEMENT_TEXT_IS.format(path="./elem/more", text="BAR"), VALID_XML, lambda x: len(x) == 0), - # test element_text_is with more specific path - (XML_ELEMENT_TEXT_IS.format(path="./elem/more[@name='baz']", text="BAZ"), VALID_XML, lambda x: len(x) == 0), - # test element_text_is .. negative test testing that prefix is not accepted - ( - XML_ELEMENT_TEXT_IS.format(path="./elem/more", text="BA"), - VALID_XML, - lambda x: "Text of element with path './elem/more': Expected text matching expression 'BA$' in output ('BAR')" - in x, - ), - # test element_attribute_matches - ( - XML_ATTRIBUTE_MATCHES.format(path="./elem/more", attribute="name", expression="ba(r|z)"), - VALID_XML, - lambda x: len(x) == 0, - ), - # test element_attribute_matches with more specific path - ( - XML_ATTRIBUTE_MATCHES.format(path="./elem/more[2]", attribute="name", expression="ba(r|z)"), - VALID_XML, - lambda x: len(x) == 0, - ), - # test element_attribute_matches .. negative test - ( - XML_ATTRIBUTE_MATCHES.format(path="./elem/more", attribute="name", expression="qu(x|y)"), - VALID_XML, - lambda x: "Attribute 'name' on element with path './elem/more': Expected text matching expression 'qu(x|y)' in output ('bar')" - in x, - ), - # test element_text - (XML_ELEMENT_TEXT.format(path="./elem/more", content_assert=""), VALID_XML, lambda x: len(x) == 0), - # test element_text .. negative - ( - XML_ELEMENT_TEXT.format(path="./absent", content_assert=""), - VALID_XML, - lambda x: "Expected path './absent' in xml" in x, - ), - # test element_text with sub-assertion - ( - XML_ELEMENT_TEXT.format(path="./elem/more", content_assert=''), - VALID_XML, - lambda x: len(x) == 0, - ), - # test element_text with sub-assertion .. negative - ( - XML_ELEMENT_TEXT.format(path="./elem/more", content_assert=''), - VALID_XML, - lambda x: "Text of element with path './elem/more': Expected text 'NOTBAR' in output ('BAR')" in x, - ), - # note that xml_element is also tested indirectly by the other xml - # assertions which are all implemented by xml_element - # test xml_element - ( + ) + assert "Text of element with path './elem/more': Expected text matching expression 'QU(X|Y)' in output ('BAR')" in a + assert len(a) == 1 + + +def test_element_text_is_sucess(): + """test element_text_is""" + a = run_assertions(XML_ELEMENT_TEXT_IS.format(path="./elem/more", text="BAR"), VALID_XML) + assert len(a) == 0 + + +def test_element_text_is_sucess_with_more_specific_path(): + """test element_text_is with more specific path""" + a = run_assertions(XML_ELEMENT_TEXT_IS.format(path="./elem/more[@name='baz']", text="BAZ"), VALID_XML) + assert len(a) == 0 + + +def test_element_text_is_failure(): + """test element_text_is .. negative test testing that prefix is not accepted""" + a = run_assertions(XML_ELEMENT_TEXT_IS.format(path="./elem/more", text="BA"), VALID_XML) + assert "Text of element with path './elem/more': Expected text matching expression 'BA$' in output ('BAR')" in a + assert len(a) == 1 + + +def test_attribute_matches_sucess(): + """est element_attribute_matches""" + a = run_assertions( + XML_ATTRIBUTE_MATCHES.format(path="./elem/more", attribute="name", expression="ba(r|z)"), VALID_XML + ) + assert len(a) == 0 + + +def test_attribute_matches_sucess_with_more_specific_path(): + """test element_attribute_matches with more specific path""" + a = run_assertions( + XML_ATTRIBUTE_MATCHES.format(path="./elem/more[2]", attribute="name", expression="ba(r|z)"), VALID_XML + ) + assert len(a) == 0 + + +def test_attribute_matches_failure(): + """test element_attribute_matches .. negative test""" + a = run_assertions( + XML_ATTRIBUTE_MATCHES.format(path="./elem/more", attribute="name", expression="qu(x|y)"), VALID_XML + ) + assert ( + "Attribute 'name' on element with path './elem/more': Expected text matching expression 'qu(x|y)' in output ('bar')" + in a + ) + assert len(a) == 1 + + +def test_element_text_success(): + """test element_text""" + a = run_assertions(XML_ELEMENT_TEXT.format(path="./elem/more", content_assert=""), VALID_XML) + assert len(a) == 0 + + +def test_element_text_failure(): + """test element_text .. negative""" + a = run_assertions(XML_ELEMENT_TEXT.format(path="./absent", content_assert=""), VALID_XML) + assert "Expected path './absent' in xml" in a + assert len(a) == 1 + + +def test_element_text_with_subassertion_sucess(): + """test element_text with sub-assertion""" + a = run_assertions(XML_ELEMENT_TEXT.format(path="./elem/more", content_assert=''), VALID_XML) + assert len(a) == 0 + + +def test_element_text_with_subassertion_failure(): + """test element_text with sub-assertion .. negative""" + a = run_assertions( + XML_ELEMENT_TEXT.format(path="./elem/more", content_assert=''), VALID_XML + ) + assert "Text of element with path './elem/more': Expected text 'NOTBAR' in output ('BAR')" in a + assert len(a) == 1 + + +# note that xml_element is also tested indirectly by the other xml +# assertions which are all implemented by xml_element +def test_xml_element_matching_text_success(): + """test xml_element""" + a = run_assertions( XML_XML_ELEMENT.format( path=".//more", n="2", @@ -641,10 +759,13 @@ negate="false", ), VALID_XML, - lambda x: len(x) == 0, - ), - # test xml_element testing attribute matching on all matching elements - ( + ) + assert len(a) == 0 + + +def test_xml_element_matching_attribute_success(): + """test xml_element testing attribute matching on all matching elements""" + a = run_assertions( XML_XML_ELEMENT.format( path=".//more", n="2", @@ -657,10 +778,13 @@ negate="false", ), VALID_XML, - lambda x: len(x) == 0, - ), - # test xml_element .. failing because of n - ( + ) + assert len(a) == 0 + + +def test_xml_element_failure_due_to_n(): + """test xml_element .. failing because of n""" + a = run_assertions( XML_XML_ELEMENT.format( path=".//more", n="2", @@ -673,10 +797,14 @@ negate="false", ), VALID_XML, - lambda x: "Expected 2+-0 occurrences of path './/more' in xml found 3" in x, - ), - # test xml_element .. failing because of n - ( + ) + assert "Expected 2+-0 occurrences of path './/more' in xml found 3" in a + assert len(a) == 1 + + +def test_xml_element_failure_due_to_minmax_in_combination_with_negate(): + """test xml_element .. failing because of n""" + a = run_assertions( XML_XML_ELEMENT.format( path=".//more", n="10000", @@ -689,10 +817,14 @@ negate="true", ), VALID_XML, - lambda x: "Did not expect that the number of occurences of path './/more' in xml is in [1:3] found 3" in x, - ), - # test xml_element .. failing because of sub assertion - ( + ) + assert "Did not expect that the number of occurences of path './/more' in xml is in [1:3] found 3" in a + assert len(a) == 1 + + +def test_xml_element_failure_due_to_subassertion(): + """test xml_element .. failing because of sub assertion""" + a = run_assertions( XML_XML_ELEMENT.format( path=".//more", n="2", @@ -705,367 +837,454 @@ negate="false", ), VALID_XML, - lambda x: "Text of element with path './/more': Did not expect text matching expression '(BA[RZ]|QUX)$' in output ('BAR')" - in x, - ), - ( - JSON_HAS_PROPERTY_WITH_VALUE.format(property="foo", value="5"), - VALID_SIMPLE_JSON, - lambda x: len(x) == 0, - ), - ( - JSON_HAS_PROPERTY_WITH_VALUE.format(property="foo", value="6"), - VALID_SIMPLE_JSON, - lambda x: "Failed to find property [foo] with JSON value [6]" in x, - ), - ( - JSON_HAS_PROPERTY_WITH_WITH.format(property="textprop", text="right"), - VALID_SIMPLE_JSON, - lambda x: len(x) == 0, - ), - ( - JSON_HAS_PROPERTY_WITH_WITH.format(property="textprop", text="wrong"), - VALID_SIMPLE_JSON, - lambda x: "Failed to find property [textprop] with text [wrong]" in x, - ), - # test has_archive_member with zip - ( - ARCHIVE_HAS_ARCHIVE_MEMBER.format(path="(\\./)?testdir/file1.txt", content_assert="", all="false"), - ZIPBYTES, - lambda x: len(x) == 0, - ), - # test has_archive_member with tar - ( - ARCHIVE_HAS_ARCHIVE_MEMBER.format(path="(\\./)?testdir/file1.txt", content_assert="", all="false"), - TARBYTES, - lambda x: len(x) == 0, - ), - # test has_archive_member with non archive - ( - ARCHIVE_HAS_ARCHIVE_MEMBER.format(path="irrelevant", content_assert="", all="false"), - NONARCHIVE, - lambda x: "Expected path 'irrelevant' to be an archive" in x, - ), - # test has_archive_member with zip on absent member - ( - ARCHIVE_HAS_ARCHIVE_MEMBER.format(path="absent", content_assert="", all="false"), - ZIPBYTES, - lambda x: "Expected path 'absent' in archive" in x, - ), - # test has_archive_member with tar on absent member - ( - ARCHIVE_HAS_ARCHIVE_MEMBER.format(path="absent", content_assert="", all="false"), - TARBYTES, - lambda x: "Expected path 'absent' in archive" in x, - ), - # test has_archive_member with zip on symlink - ( + ) + assert ( + "Text of element with path './/more': Did not expect text matching expression '(BA[RZ]|QUX)$' in output ('BAR')" + in a + ) + assert len(a) == 1 + + +# create a test directory structure for zipping +# might also be done directly with the fipfile/tarfile module without creating +# a tmpdir, but its much harder to create empty directories or symlinks +tmpdir = tempfile.mkdtemp() +for f in ["file1.txt", "testdir/file1.txt", "testdir/file2.txt", "testdir/dir2/file1.txt"]: + tmpfile = os.path.join(tmpdir, f) + os.makedirs(os.path.dirname(tmpfile), exist_ok=True) + with open(tmpfile, "w") as fh: + fh.write(f) +os.makedirs(os.path.join(tmpdir, "emptydir")) +os.symlink("testdir/file1.txt", os.path.join(tmpdir, "symlink")) + +with tempfile.NamedTemporaryFile(suffix=".zip", delete=False) as ziptmp: + zipname = ziptmp.name + shutil.make_archive(zipname[:-4], "zip", tmpdir) + with open(zipname, "rb") as zfh: + ZIPBYTES = zfh.read() +with tempfile.NamedTemporaryFile(suffix=".tar.gz", delete=False) as ziptmp: + zipname = ziptmp.name + shutil.make_archive(zipname[:-7], "gztar", tmpdir) + with open(zipname, "rb") as zfh: + TARBYTES = zfh.read() +shutil.rmtree(tmpdir) + + +with tempfile.NamedTemporaryFile(mode="w", delete=False) as nonarchivetmp: + nonarchivename = nonarchivetmp.name + nonarchivetmp.write("some text") +with open(nonarchivename, "rb") as ntmp: + NONARCHIVE = ntmp.read() + +ARCHIVE_HAS_ARCHIVE_MEMBER = """ + + + {content_assert} + + +""" + +ARCHIVE_HAS_ARCHIVE_MEMBER_N = """ + + + {content_assert} + + +""" + +ARCHIVE_HAS_ARCHIVE_MEMBER_MINMAX = """ + + + {content_assert} + + +""" + + +def test_has_archive_member_zip(): + """test has_archive_member with zip""" + a = run_assertions( + ARCHIVE_HAS_ARCHIVE_MEMBER.format(path="(\\./)?testdir/file1.txt", content_assert="", all="false"), ZIPBYTES + ) + assert len(a) == 0 + + +def test_has_archive_member_tar(): + """test has_archive_member with tar""" + a = run_assertions( + ARCHIVE_HAS_ARCHIVE_MEMBER.format(path="(\\./)?testdir/file1.txt", content_assert="", all="false"), TARBYTES + ) + assert len(a) == 0 + + +def test_has_archive_member_nonarchive(): + """test has_archive_member with non archive""" + a = run_assertions(ARCHIVE_HAS_ARCHIVE_MEMBER.format(path="irrelevant", content_assert="", all="false"), NONARCHIVE) + assert "Expected path 'irrelevant' to be an archive" in a + assert len(a) == 1 + + +def test_has_archive_member_zip_absent_member(): + """test has_archive_member with zip on absent member""" + a = run_assertions(ARCHIVE_HAS_ARCHIVE_MEMBER.format(path="absent", content_assert="", all="false"), ZIPBYTES) + assert "Expected path 'absent' in archive" in a + assert len(a) == 1 + + +def test_has_archive_member_tar_absent_member(): + """test has_archive_member with tar on absent member""" + a = run_assertions(ARCHIVE_HAS_ARCHIVE_MEMBER.format(path="absent", content_assert="", all="false"), TARBYTES) + assert "Expected path 'absent' in archive" in a + assert len(a) == 1 + + +def test_has_archive_member_zip_symlink_member(): + """test has_archive_member with zip on symlink""" + a = run_assertions( ARCHIVE_HAS_ARCHIVE_MEMBER.format( path="(\\./)?symlink", content_assert='', all="false" ), ZIPBYTES, - lambda x: len(x) == 0, - ), - # test has_archive_member with tar on symlink - ( + ) + assert len(a) == 0 + + +def test_has_archive_member_tar_symlink_member(): + """test has_archive_member with tar on symlink""" + a = run_assertions( ARCHIVE_HAS_ARCHIVE_MEMBER.format( path="(\\./)?symlink", content_assert='', all="false" ), TARBYTES, - lambda x: len(x) == 0, - ), - # test has_archive_member with zip on a dir member (which are treated like empty files) - ( + ) + assert len(a) == 0 + + +def test_has_archive_member_zip_nonfile_member(): + """test has_archive_member with zip on a dir member (which are treated like empty files)""" + a = run_assertions( ARCHIVE_HAS_ARCHIVE_MEMBER.format(path="(\\./)?testdir/", content_assert='', all="false"), ZIPBYTES, - lambda x: len(x) == 0, - ), - # test has_archive_member with tar on a dir member (which are treated like empty files) - ( + ) + assert len(a) == 0 + + +def test_has_archive_member_tar_nonfile_member(): + """test has_archive_member with tar on a dir member (which are treated like empty files)""" + a = run_assertions( ARCHIVE_HAS_ARCHIVE_MEMBER.format(path="(\\./)?testdir/", content_assert='', all="false"), TARBYTES, - lambda x: len(x) == 0, - ), - # test has_archive_member with zip with subassertion (note that archive members are sorted therefor file1 in dir2 is tested) - ( + ) + assert len(a) == 0 + + +def test_has_archive_member_zip_with_content_assertion(): + """test has_archive_member with zip with subassertion (note that archive members are sorted therefor file1 in dir2 is tested)""" + a = run_assertions( ARCHIVE_HAS_ARCHIVE_MEMBER.format( path="(\\./)?testdir/.*\\.txt", content_assert='', all="false" ), ZIPBYTES, - lambda x: len(x) == 0, - ), - # test has_archive_member with tar with subassertion (note that archive members are sorted therefor file1 in dir2 is tested) - ( + ) + assert len(a) == 0 + + +def test_has_archive_member_tar_with_content_assertion(): + """test has_archive_member with tar with subassertion (note that archive members are sorted therefor file1 in dir2 is tested)""" + a = run_assertions( ARCHIVE_HAS_ARCHIVE_MEMBER.format( path="(\\./)?testdir/.*\\.txt", content_assert='', all="false" ), TARBYTES, - lambda x: len(x) == 0, - ), - # test has_archive_member with zip with failing subassertion - ( + ) + assert len(a) == 0 + + +def test_has_archive_member_zip_with_failing_content_assertion(): + """test has_archive_member with zip with failing subassertion""" + a = run_assertions( ARCHIVE_HAS_ARCHIVE_MEMBER.format( path="(\\./)?testdir/file1.txt", content_assert='', all="false" ), ZIPBYTES, - lambda x: "Archive member '(\\./)?testdir/file1.txt': Expected text 'ABSENT' in output ('testdir/file1.txt')" - in x, - ), - # test has_archive_member with tar with failing subassertion - ( + ) + assert "Archive member '(\\./)?testdir/file1.txt': Expected text 'ABSENT' in output ('testdir/file1.txt')" in a + assert len(a) == 1 + + +def test_has_archive_member_tar_with_failing_content_assertion(): + """test has_archive_member with tar with failing subassertion""" + a = run_assertions( ARCHIVE_HAS_ARCHIVE_MEMBER.format( path="(\\./)?testdir/file1.txt", content_assert='', all="false" ), TARBYTES, - lambda x: "Archive member '(\\./)?testdir/file1.txt': Expected text 'ABSENT' in output ('testdir/file1.txt')" - in x, - ), - # test has_archive_member with zip checking all matches with subassertion - ( + ) + assert "Archive member '(\\./)?testdir/file1.txt': Expected text 'ABSENT' in output ('testdir/file1.txt')" in a + assert len(a) == 1 + + +def test_has_archive_member_zip_all_matching_with_content_assertion(): + """test has_archive_member with zip checking all matches with subassertion""" + a = run_assertions( ARCHIVE_HAS_ARCHIVE_MEMBER.format( path=".*file.\\.txt", content_assert='', all="true" ), ZIPBYTES, - lambda x: len(x) == 0, - ), - # test has_archive_member with tar checking all matches with subassertion - ( + ) + assert len(a) == 0 + + +def test_has_archive_member_tar_all_matching_with_content_assertion(): + """test has_archive_member with tar checking all matches with subassertion""" + a = run_assertions( ARCHIVE_HAS_ARCHIVE_MEMBER.format( path=".*file.\\.txt", content_assert='', all="true" ), TARBYTES, - lambda x: len(x) == 0, - ), - # test has_archive_member with zip checking all matches with failing subassertion - ( + ) + assert len(a) == 0 + + +def test_has_archive_member_zip_all_matching_with_failing_content_assertion(): + """test has_archive_member with zip checking all matches with failing subassertion""" + a = run_assertions( ARCHIVE_HAS_ARCHIVE_MEMBER.format( path=".*file.\\.txt", content_assert='', all="true" ), ZIPBYTES, - lambda x: "Expected text matching expression 'file1\\.txt' in output ('testdir/file2.txt')", - ), - # test has_archive_member with tar checking all matches with failing subassertion - ( + ) + assert "Expected text matching expression 'file1\\.txt' in output ('testdir/file2.txt')" + assert len(a) == 1 + + +def test_has_archive_member_tar_all_matching_with_failing_content_assertion(): + """test has_archive_member with tar checking all matches with failing subassertion""" + a = run_assertions( ARCHIVE_HAS_ARCHIVE_MEMBER.format( path=".*file.\\.txt", content_assert='', all="true" ), TARBYTES, - lambda x: "Expected text matching expression 'file1\\.txt' in output ('testdir/file2.txt')", - ), - # test has_archive_member with zip n+delta with subassertion - ( + ) + + assert ( + "Archive member '.*file.\\.txt': Expected text matching expression 'file1\\.txt' in output ('testdir/file2.txt')" + in a + ) + assert len(a) == 1 + + +def test_has_archive_member_zip_n_delta_and_content_assertion(): + """test has_archive_member with zip n+delta with subassertion""" + a = run_assertions( ARCHIVE_HAS_ARCHIVE_MEMBER_N.format( path=".*file.\\.txt", content_assert='', n="3", delta="1" ), ZIPBYTES, - lambda x: len(x) == 0, - ), - # test has_archive_member with zip n+delta with subassertion .. negative - ( + ) + assert len(a) == 0 + + +def test_has_archive_member_zip_n_delta_failing_and_content_assertion(): + """test has_archive_member with zip n+delta with subassertion .. negative""" + a = run_assertions( ARCHIVE_HAS_ARCHIVE_MEMBER_N.format( path=".*file.\\.txt", content_assert='', n="1", delta="1" ), ZIPBYTES, - lambda x: "Expected 1+-1 matches for path '.*file.\\.txt' in archive found 4" in x, - ), - # test has_archive_member with tar n+delta with subassertion - ( + ) + assert "Expected 1+-1 matches for path '.*file.\\.txt' in archive found 4" in a + assert len(a) == 1 + + +def test_has_archive_member_tar_n_delta_and_content_assertion(): + """test has_archive_member with tar n+delta with subassertion""" + a = run_assertions( ARCHIVE_HAS_ARCHIVE_MEMBER_N.format( path=".*file.\\.txt", content_assert='', n="3", delta="1" ), TARBYTES, - lambda x: len(x) == 0, - ), - # test has_archive_member with tar n+delta with subassertion .. negative - ( + ) + assert len(a) == 0 + + +def test_has_archive_member_tar_n_delta_failing_and_content_assertion(): + """test has_archive_member with tar n+delta with subassertion .. negative""" + a = run_assertions( ARCHIVE_HAS_ARCHIVE_MEMBER_N.format( path=".*file.\\.txt", content_assert='', n="1", delta="1" ), TARBYTES, - lambda x: "Expected 1+-1 matches for path '.*file.\\.txt' in archive found 4" in x, - ), - # test has_archive_member with zip min+max with subassertion - ( + ) + assert "Expected 1+-1 matches for path '.*file.\\.txt' in archive found 4" in a + assert len(a) == 1 + + +def test_has_archive_member_zip_min_max_and_content_assertion(): + """test has_archive_member with zip min+max with subassertion""" + a = run_assertions( ARCHIVE_HAS_ARCHIVE_MEMBER_MINMAX.format( path=".*file.\\.txt", content_assert='', min="2", max="4" ), ZIPBYTES, - lambda x: len(x) == 0, - ), - # test has_archive_member with zip min+max with subassertion .. negative - ( + ) + assert len(a) == 0 + + +def test_has_archive_member_zip_min_max_failing_and_content_assertion(): + """test has_archive_member with zip min+max with subassertion .. negative""" + a = run_assertions( ARCHIVE_HAS_ARCHIVE_MEMBER_MINMAX.format( path=".*file.\\.txt", content_assert='', min="0", max="2" ), ZIPBYTES, - lambda x: "Expected that the number of matches for path '.*file.\\.txt' in archive is in [0:2] found 4" in x, - ), - # test has_archive_member with tar min+max with subassertion - ( + ) + assert "Expected that the number of matches for path '.*file.\\.txt' in archive is in [0:2] found 4" in a + assert len(a) == 1 + + +def test_has_archive_member_tar_min_max_and_content_assertion(): + """test has_archive_member with tar min+max with subassertion""" + a = run_assertions( ARCHIVE_HAS_ARCHIVE_MEMBER_MINMAX.format( path=".*file.\\.txt", content_assert='', min="2", max="4" ), TARBYTES, - lambda x: len(x) == 0, - ), - # test has_archive_member with tar min+max with subassertion .. negative - ( + ) + assert len(a) == 0 + + +def test_has_archive_member_tar_min_max_failing_and_content_assertion(): + """test has_archive_member with tar min+max with subassertion .. negative""" + a = run_assertions( ARCHIVE_HAS_ARCHIVE_MEMBER_MINMAX.format( path=".*file.\\.txt", content_assert='', min="0", max="2" ), TARBYTES, - lambda x: "Expected that the number of matches for path '.*file.\\.txt' in archive is in [0:2] found 4" in x, - ), -] + ) + assert "Expected that the number of matches for path '.*file.\\.txt' in archive is in [0:2] found 4" in a + assert len(a) == 1 + + +JSON_HAS_PROPERTY_WITH_VALUE = """ + + + +""" + +JSON_HAS_PROPERTY_WITH_TEXT = """ + + + +""" + +VALID_SIMPLE_JSON = """{"foo": 5, "list": [{"textprop": "right"}]}""" + + +def test_has_json_property_with_value_pos(): + """positive test for has_json_property_with_value""" + a = run_assertions( + JSON_HAS_PROPERTY_WITH_VALUE.format(property="foo", value="5"), + VALID_SIMPLE_JSON, + ) + assert len(a) == 0 + + +def test_has_json_property_with_value_neg(): + """negative test for has_json_property_with_value""" + a = run_assertions( + JSON_HAS_PROPERTY_WITH_VALUE.format(property="foo", value="6"), + VALID_SIMPLE_JSON, + ) + assert "Failed to find property [foo] with JSON value [6]" in a + assert len(a) == 1 + + +def test_has_json_property_with_text_pos(): + """positive test for has_json_property_with_text""" + a = run_assertions( + JSON_HAS_PROPERTY_WITH_TEXT.format(property="textprop", text="right"), + VALID_SIMPLE_JSON, + ) + assert len(a) == 0 + + +def test_has_json_property_with_text_neg(): + """negative test for has_json_property_with_text""" + a = run_assertions( + JSON_HAS_PROPERTY_WITH_TEXT.format(property="textprop", text="wrong"), + VALID_SIMPLE_JSON, + ) + assert "Failed to find property [textprop] with text [wrong]" in a + assert len(a) == 1 -if h5py is not None: - H5PY_TESTS = [ - # test has_h5_keys - (H5_HAS_H5_KEYS, H5BYTES, lambda x: len(x) == 0), - # test has_h5_keys .. negative - ( - H5_HAS_H5_KEYS_NEGATIVE, - H5BYTES, - lambda x: "Not a HDF5 file or H5 keys missing:\n\t['mygroup', 'mygroup/myfloat', 'myint']\n\t['absent']" - in x, - ), - # test has_attribute - (H5_HAS_ATTRIBUTE, H5BYTES, lambda x: len(x) == 0), - # test has_attribute .. negative - ( - H5_HAS_ATTRIBUTE_NEGATIVE, - H5BYTES, - lambda x: "Not a HDF5 file or H5 attributes do not match:\n\t[('myfileattr', 'myfileattrvalue'), ('myfileattrint', 1)]\n\n\t(myfileattr : wrong)" - in x, - ), - ] - TESTS.extend(H5PY_TESTS) - - -TEST_IDS = [ - "has_n_columns success", - "has_n_columns failure", - "has_n_columns for csv", - "has_n_columns with comments", - "has_text success", - "has_text failure", - "has_text None output", - "has_text empty output", - "has_text n success", - "has_text n failure", - "has_text n delta success", - "has_text n delta failure", - "has_text min/max delta success", - "has_text min/max delta failure", - "has_text negate success", - "has_text negate failure", - "has_text negate None output", - "has_text negate empty output", - "has_text negate n success", - "has_text negate n failure", - "has_text negate n delta success", - "has_text negate n delta failure", - "has_text negate min/max delta success", - "has_text negate min/max delta failure", - "not_has_text success", - "not_has_text failure", - "not_has_text None output", - "not_has_text empty output", - "has_text_matching success", - "has_text_matching failure", - "has_text_matching n success", - "has_text_matching n failure", - "has_text_matching min/max success", - "has_text_matching min/max failure", - "has_line success", - "has_line failure", - "has_line n success", - "has_line n failure", - "has_n_lines success", - "has_n_lines n as bytes success", - "has_n_lines failure", - "has_n_lines delta", - "has_line_matching success", - "has_line_matching failure", - "has_line_matching n success", - "has_line_matching n failure", - "has_size success", - "has_size failure", - "has_size delta", - "has_size with bytes suffix", - "has_size with bytes suffix failure", - "is_valid_xml success", - "is_valid_xml failure", - "has_element_with_path success 1", - "has_element_with_path success 2", - "has_element_with_path success 3", - "has_element_with_path failure", - "has_n_elements_with_path success 1", - "has_n_elements_with_path success 2", - "has_n_elements_with_path success 3", - "has_n_elements_with_path success 4", - "has_n_elements_with_path failure", - "element_text_matches sucess", - "element_text_matches sucess (with more specific path)", - "element_text_matches failure", - "element_text_is sucess", - "element_text_is sucess (with more specific path)", - "element_text_is failure", - "attribute_matches sucess", - "attribute_matches sucess (with more specific path)", - "attribute_matches failure", - "element_text success", - "element_text failure", - "element_text with subassertion sucess", - "element_text with subassertion failure", - "xml_element matching text success", - "xml_element matching attribute success", - "xml_element failure (due to n)", - "xml_element failure (due to min/max in combination with negate)", - "xml_element failure (due to subassertion)", - "has_json_property_with_value success", - "has_json_property_with_value failure", - "has_json_property_with_text success", - "has_json_property_with_text failure", - "has_archive_member zip", - "has_archive_member tar", - "has_archive_member non-archive", - "has_archive_member zip absent member", - "has_archive_member tar absent member", - "has_archive_member zip symlink member", - "has_archive_member tar symlink member", - "has_archive_member zip non-file member", - "has_archive_member tar non-file member", - "has_archive_member zip with content assertion", - "has_archive_member tar with content assertion", - "has_archive_member zip with failing content assertion", - "has_archive_member tar with failing content assertion", - "has_archive_member zip all matching with content assertion", - "has_archive_member tar all matching with content assertion", - "has_archive_member zip all matching with failing content assertion", - "has_archive_member tar all matching with failing content assertion", - "has_archive_member zip n + delta and content assertion", - "has_archive_member zip n + delta failing and content assertion", - "has_archive_member tar n + delta and content assertion", - "has_archive_member tar n + delta failing and content assertion", - "has_archive_member zip min max and content assertion", - "has_archive_member zip min max failing and content assertion", - "has_archive_member tar min max and content assertion", - "has_archive_member tar min max failing and content assertion", -] if h5py is not None: - H5PY_TEST_IDS = [ - "has_h5_keys", - "has_h5_keys failure", - "has_h5_attribute", - "has_h5_attribute failure", - ] - TEST_IDS.extend(H5PY_TEST_IDS) + with tempfile.NamedTemporaryFile(delete=False) as tmp: + h5name = tmp.name + with h5py.File(tmp.name, "w") as h5fh: + h5fh.attrs["myfileattr"] = "myfileattrvalue" + h5fh.attrs["myfileattrint"] = 1 + dset = h5fh.create_dataset("myint", (100,), dtype="i") + dset.attrs["myintattr"] = "myintattrvalue" + grp = h5fh.create_group("mygroup") + grp.attrs["mygroupattr"] = "mygroupattrvalue" + grp.create_dataset("myfloat", (50,), dtype="f") + dset.attrs["myfloatattr"] = "myfloatattrvalue" + with open(h5name, "rb") as h5fh: + H5BYTES = h5fh.read() + os.remove(h5name) + + H5_HAS_H5_KEYS = """ + + + + """ + H5_HAS_H5_KEYS_NEGATIVE = """ + + + + """ + H5_HAS_ATTRIBUTE = """ + + + + + """ + H5_HAS_ATTRIBUTE_NEGATIVE = """ + + + + + """ + + def test_has_h5_keys(): + """test has_h5_keys""" + a = run_assertions(H5_HAS_H5_KEYS, H5BYTES) + assert len(a) == 0 + + def test_has_h5_keys_failure(): + """test has_h5_keys .. negative""" + a = run_assertions(H5_HAS_H5_KEYS_NEGATIVE, H5BYTES) + assert "Not a HDF5 file or H5 keys missing:\n\t['mygroup', 'mygroup/myfloat', 'myint']\n\t['absent']" in a + assert len(a) == 1 + + def test_has_h5_attribute(): + """test has_attribut""" + a = run_assertions(H5_HAS_ATTRIBUTE, H5BYTES) + assert len(a) == 0 + + def test_has_h5_attribute_failure(): + """test has_attribute .. negative""" + a = run_assertions(H5_HAS_ATTRIBUTE_NEGATIVE, H5BYTES) + assert ( + "Not a HDF5 file or H5 attributes do not match:\n\t[('myfileattr', 'myfileattrvalue'), ('myfileattrint', 1)]\n\n\t(myfileattr : wrong)" + in a + ) + assert len(a) == 1 -@pytest.mark.parametrize("assertion_xml,data,assert_func", TESTS, ids=TEST_IDS) -def test_assertions(assertion_xml, data, assert_func): +def run_assertions(assertion_xml, data): assertion = etree.fromstring(assertion_xml) assertion_description = __parse_assert_list_from_elem(assertion) try: @@ -1074,4 +1293,4 @@ def test_assertions(assertion_xml, data, assert_func): assert_list = e.args else: assert_list = () - assert assert_func(assert_list), assert_list + return assert_list From 2aee13651186471d1274a7f066156e5145310c0f Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Fri, 16 Dec 2022 20:37:45 +0100 Subject: [PATCH 4/6] add unit and functional tests for decomress with assertions --- test/functional/tools/validation_tar_gz.xml | 42 +++++++++++++++++++++ test/unit/tool_util/verify/test_asserts.py | 34 ++++++++++++++++- 2 files changed, 74 insertions(+), 2 deletions(-) diff --git a/test/functional/tools/validation_tar_gz.xml b/test/functional/tools/validation_tar_gz.xml index e10a3e07c90e..759ae1514464 100644 --- a/test/functional/tools/validation_tar_gz.xml +++ b/test/functional/tools/validation_tar_gz.xml @@ -1,4 +1,7 @@ + '$output' ]]> @@ -9,10 +12,49 @@ cat '$input' > '$output' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/unit/tool_util/verify/test_asserts.py b/test/unit/tool_util/verify/test_asserts.py index e98f345d4719..cb415507c530 100644 --- a/test/unit/tool_util/verify/test_asserts.py +++ b/test/unit/tool_util/verify/test_asserts.py @@ -1,3 +1,4 @@ +import gzip import os import shutil import tempfile @@ -479,6 +480,13 @@ def test_has_line_matching_n_failure(): """ +# create gz test data for use with has_size tests +with tempfile.NamedTemporaryFile(mode="w", delete=False) as txttmp: + txttmp.write("A" * 100) + txttmp.flush() + A100 = open(txttmp.name, "rb").read() + GZA100 = gzip.compress(A100) + def test_has_size_success(): """test has_size""" @@ -512,6 +520,21 @@ def test_has_size_with_bytes_suffix_failure(): 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) + assert len(a) == 0 + + +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) + assert len(a) == 0 + + VALID_XML = """ BAR @@ -901,6 +924,13 @@ def test_xml_element_failure_due_to_subassertion(): """ +def test_has_archive_member_1filegzip(): + """test has_archive_member with a single file gz which should fail (has no members anyway)""" + a = run_assertions(ARCHIVE_HAS_ARCHIVE_MEMBER.format(path="(\\./)?xyz", content_assert="", all="false"), GZA100) + assert "Expected path '(\\./)?xyz' to be an archive" in a + assert len(a) == 1 + + def test_has_archive_member_zip(): """test has_archive_member with zip""" a = run_assertions( @@ -1284,11 +1314,11 @@ def test_has_h5_attribute_failure(): assert len(a) == 1 -def run_assertions(assertion_xml, data): +def run_assertions(assertion_xml, data, decompress=None): assertion = etree.fromstring(assertion_xml) assertion_description = __parse_assert_list_from_elem(assertion) try: - asserts.verify_assertions(data, assertion_description) + asserts.verify_assertions(data, assertion_description, decompress=decompress) except AssertionError as e: assert_list = e.args else: From 5e96224a54f7a1b4ec2d3a709ccdd0d873077ee9 Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Fri, 16 Dec 2022 20:38:29 +0100 Subject: [PATCH 5/6] extend xsd for decompress attribute --- lib/galaxy/tool_util/xsd/galaxy.xsd | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/galaxy/tool_util/xsd/galaxy.xsd b/lib/galaxy/tool_util/xsd/galaxy.xsd index 86e0038a3423..a6be00c9d8ff 100644 --- a/lib/galaxy/tool_util/xsd/galaxy.xsd +++ b/lib/galaxy/tool_util/xsd/galaxy.xsd @@ -1730,7 +1730,10 @@ but ``sim_size``. This flag is useful for testing compressed outputs that are non-deterministic despite having deterministic decompressed contents. By default, only files compressed with bz2, gzip and zip will be automatically decompressed. -This is available in Galaxy since release 17.05 and was introduced in [pull request #3550](https://github.com/galaxyproject/galaxy/pull/3550). +Note, for specifying assertions for compressed as well as decompressed output +the corresponding output tag can be specified multiple times. +This is available in Galaxy since release 17.05 and was introduced in [pull request #3550](https://github.com/galaxyproject/galaxy/pull/3550) +the application to content assertions has been introduced in 23.0 [pull request #15085](https://github.com/galaxyproject/galaxy/pull/15085). ]]> From fcb98097af5bd758864c7e9d5b11780cb98f8606 Mon Sep 17 00:00:00 2001 From: M Bernt Date: Thu, 27 Apr 2023 17:49:28 +0200 Subject: [PATCH 6/6] Update lib/galaxy/tool_util/xsd/galaxy.xsd --- lib/galaxy/tool_util/xsd/galaxy.xsd | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/galaxy/tool_util/xsd/galaxy.xsd b/lib/galaxy/tool_util/xsd/galaxy.xsd index a6be00c9d8ff..ef5b3df9c73d 100644 --- a/lib/galaxy/tool_util/xsd/galaxy.xsd +++ b/lib/galaxy/tool_util/xsd/galaxy.xsd @@ -1732,8 +1732,7 @@ despite having deterministic decompressed contents. By default, only files compr with bz2, gzip and zip will be automatically decompressed. Note, for specifying assertions for compressed as well as decompressed output the corresponding output tag can be specified multiple times. -This is available in Galaxy since release 17.05 and was introduced in [pull request #3550](https://github.com/galaxyproject/galaxy/pull/3550) -the application to content assertions has been introduced in 23.0 [pull request #15085](https://github.com/galaxyproject/galaxy/pull/15085). +This is available in Galaxy since release 17.05 and was introduced in [pull request #3550](https://github.com/galaxyproject/galaxy/pull/3550). ]]>