diff --git a/swh/web/tests/api/views/test_identifiers.py b/swh/web/tests/api/views/test_identifiers.py --- a/swh/web/tests/api/views/test_identifiers.py +++ b/swh/web/tests/api/views/test_identifiers.py @@ -3,19 +3,11 @@ # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information -from hypothesis import given from swh.model.swhids import ObjectType from swh.web.common.identifiers import gen_swhid from swh.web.common.utils import reverse from swh.web.tests.data import random_sha1 -from swh.web.tests.strategies import ( - unknown_content, - unknown_directory, - unknown_release, - unknown_revision, - unknown_snapshot, -) from swh.web.tests.utils import check_api_get_responses, check_api_post_responses @@ -72,13 +64,6 @@ check_api_get_responses(api_client, url, status_code=400) -@given( - unknown_content(), - unknown_directory(), - unknown_release(), - unknown_revision(), - unknown_snapshot(), -) def test_swhid_resolve_not_found( api_client, unknown_content, diff --git a/swh/web/tests/api/views/test_vault.py b/swh/web/tests/api/views/test_vault.py --- a/swh/web/tests/api/views/test_vault.py +++ b/swh/web/tests/api/views/test_vault.py @@ -5,13 +5,11 @@ import re -from hypothesis import given import pytest from swh.model.swhids import CoreSWHID from swh.vault.exc import NotFoundExc from swh.web.common.utils import reverse -from swh.web.tests.strategies import unknown_directory, unknown_revision from swh.web.tests.utils import ( check_api_get_responses, check_api_post_responses, @@ -72,7 +70,6 @@ mock_archive.vault_fetch.assert_called_with(bundle_type, swhid) -@given(unknown_directory(), unknown_revision()) def test_api_vault_cook_notfound( api_client, mocker, directory, revision, unknown_directory, unknown_revision ): @@ -271,7 +268,6 @@ assert rv["location"] == redirect_url -@given(unknown_directory(), unknown_revision()) def test_api_vault_cook_notfound_legacy( api_client, mocker, directory, revision, unknown_directory, unknown_revision ): diff --git a/swh/web/tests/browse/views/test_content.py b/swh/web/tests/browse/views/test_content.py --- a/swh/web/tests/browse/views/test_content.py +++ b/swh/web/tests/browse/views/test_content.py @@ -5,8 +5,6 @@ import random -from hypothesis import given - from django.utils.html import escape from swh.model.swhids import ObjectType @@ -20,7 +18,6 @@ from swh.web.common.identifiers import gen_swhid from swh.web.common.utils import gen_path_info, reverse from swh.web.tests.django_asserts import assert_contains, assert_not_contains -from swh.web.tests.strategies import invalid_sha1, unknown_content from swh.web.tests.utils import check_html_get_response, check_http_get_response @@ -318,7 +315,6 @@ assert resp.content == content_data -@given(invalid_sha1(), unknown_content()) def test_content_request_errors(client, invalid_sha1, unknown_content): url = reverse("browse-content", url_args={"query_string": invalid_sha1}) check_html_get_response(client, url, status_code=400, template_used="error.html") diff --git a/swh/web/tests/browse/views/test_directory.py b/swh/web/tests/browse/views/test_directory.py --- a/swh/web/tests/browse/views/test_directory.py +++ b/swh/web/tests/browse/views/test_directory.py @@ -30,12 +30,7 @@ from swh.web.common.identifiers import gen_swhid from swh.web.common.utils import gen_path_info, reverse from swh.web.tests.django_asserts import assert_contains, assert_not_contains -from swh.web.tests.strategies import ( - invalid_sha1, - new_person, - new_swh_date, - unknown_directory, -) +from swh.web.tests.strategies import new_person, new_swh_date from swh.web.tests.utils import check_html_get_response @@ -134,7 +129,6 @@ ) -@given(invalid_sha1(), unknown_directory()) def test_directory_request_errors(client, invalid_sha1, unknown_directory): dir_url = reverse("browse-directory", url_args={"sha1_git": invalid_sha1}) diff --git a/swh/web/tests/browse/views/test_origin.py b/swh/web/tests/browse/views/test_origin.py --- a/swh/web/tests/browse/views/test_origin.py +++ b/swh/web/tests/browse/views/test_origin.py @@ -33,12 +33,7 @@ ) from swh.web.tests.data import get_content, random_sha1 from swh.web.tests.django_asserts import assert_contains, assert_not_contains -from swh.web.tests.strategies import ( - new_origin, - new_snapshot, - unknown_revision, - visit_dates, -) +from swh.web.tests.strategies import new_origin, new_snapshot, visit_dates from swh.web.tests.utils import check_html_get_response @@ -773,9 +768,9 @@ ) -@given(new_origin(), unknown_revision()) +@given(new_origin()) def test_origin_browse_directory_branch_with_non_resolvable_revision( - client, archive_data, new_origin, unknown_revision + client, archive_data, unknown_revision, new_origin, ): branch_name = "master" snapshot = Snapshot( diff --git a/swh/web/tests/browse/views/test_release.py b/swh/web/tests/browse/views/test_release.py --- a/swh/web/tests/browse/views/test_release.py +++ b/swh/web/tests/browse/views/test_release.py @@ -5,15 +5,12 @@ import random -from hypothesis import given - from django.utils.html import escape from swh.model.swhids import ObjectType from swh.web.common.identifiers import gen_swhid from swh.web.common.utils import format_utc_iso_date, reverse from swh.web.tests.django_asserts import assert_contains -from swh.web.tests.strategies import unknown_release from swh.web.tests.utils import check_html_get_response @@ -45,7 +42,6 @@ ) -@given(unknown_release()) def test_release_browse_not_found(client, archive_data, unknown_release): url = reverse("browse-release", url_args={"sha1_git": unknown_release}) diff --git a/swh/web/tests/browse/views/test_revision.py b/swh/web/tests/browse/views/test_revision.py --- a/swh/web/tests/browse/views/test_revision.py +++ b/swh/web/tests/browse/views/test_revision.py @@ -16,12 +16,7 @@ from swh.web.common.identifiers import gen_swhid from swh.web.common.utils import format_utc_iso_date, parse_iso8601_date_to_utc, reverse from swh.web.tests.django_asserts import assert_contains, assert_not_contains -from swh.web.tests.strategies import ( - new_origin, - new_person, - new_swh_date, - unknown_revision, -) +from swh.web.tests.strategies import new_origin, new_person, new_swh_date from swh.web.tests.utils import check_html_get_response @@ -155,7 +150,7 @@ ) -@given(unknown_revision(), new_origin()) +@given(new_origin()) def test_revision_request_errors(client, revision, unknown_revision, new_origin): url = reverse("browse-revision", url_args={"sha1_git": unknown_revision}) diff --git a/swh/web/tests/common/test_archive.py b/swh/web/tests/common/test_archive.py --- a/swh/web/tests/common/test_archive.py +++ b/swh/web/tests/common/test_archive.py @@ -29,19 +29,7 @@ from swh.web.common.typing import OriginInfo, PagedResult from swh.web.tests.conftest import ctags_json_missing, fossology_missing from swh.web.tests.data import random_content, random_sha1 -from swh.web.tests.strategies import ( - invalid_sha1, - new_origin, - new_revision, - sha256, - unknown_content, - unknown_contents, - unknown_directory, - unknown_release, - unknown_revision, - unknown_snapshot, - visit_dates, -) +from swh.web.tests.strategies import new_origin, new_revision, visit_dates def test_lookup_multiple_hashes_all_present(contents): @@ -54,7 +42,6 @@ assert archive.lookup_multiple_hashes(input_data) == expected_output -@given(unknown_contents()) def test_lookup_multiple_hashes_some_missing(contents, unknown_contents): input_contents = list(itertools.chain(contents, unknown_contents)) random.shuffle(input_contents) @@ -229,14 +216,12 @@ assert actual_origin == expected_origin -@given(invalid_sha1()) def test_lookup_release_ko_id_checksum_not_a_sha1(invalid_sha1): with pytest.raises(BadInputExc) as e: archive.lookup_release(invalid_sha1) assert e.match("Invalid checksum") -@given(sha256()) def test_lookup_release_ko_id_checksum_too_long(sha256): with pytest.raises(BadInputExc) as e: archive.lookup_release(sha256) @@ -285,7 +270,6 @@ assert actual_release == archive_data.release_get(release) -@given(invalid_sha1(), sha256()) def test_lookup_revision_with_context_ko_not_a_sha1(revision, invalid_sha1, sha256): sha1_git_root = revision sha1_git = invalid_sha1 @@ -301,7 +285,6 @@ assert e.match("Only sha1_git is supported") -@given(unknown_revision()) def test_lookup_revision_with_context_ko_sha1_git_does_not_exist( revision, unknown_revision ): @@ -313,7 +296,6 @@ assert e.match("Revision %s not found" % sha1_git) -@given(unknown_revision()) def test_lookup_revision_with_context_ko_root_sha1_git_does_not_exist( revision, unknown_revision ): @@ -500,7 +482,7 @@ revision = archive.lookup_revision(hash_to_hex(new_revision["id"])) assert revision["message"] == "elegant fix for bug \\xff" - assert revision["decoding_failures"] == ["message"] + assert "message" in revision["decoding_failures"] @given(new_revision()) @@ -814,13 +796,6 @@ assert archive.lookup_object(ObjectType.SNAPSHOT, snapshot) == expected -@given( - unknown_content(), - unknown_directory(), - unknown_release(), - unknown_revision(), - unknown_snapshot(), -) def test_lookup_unknown_objects( unknown_content, unknown_directory, @@ -849,7 +824,6 @@ assert e.match(r"Snapshot.*not found") -@given(invalid_sha1()) def test_lookup_invalid_objects(invalid_sha1): with pytest.raises(BadInputExc) as e: diff --git a/swh/web/tests/conftest.py b/swh/web/tests/conftest.py --- a/swh/web/tests/conftest.py +++ b/swh/web/tests/conftest.py @@ -40,7 +40,13 @@ from swh.web.common.typing import OriginVisitInfo from swh.web.common.utils import browsers_supported_image_mimes from swh.web.config import get_config -from swh.web.tests.data import get_tests_data, override_storages +from swh.web.tests.data import ( + get_tests_data, + override_storages, + random_content, + random_sha1, + random_sha256, +) # Used to skip some tests ctags_json_missing = ( @@ -166,6 +172,27 @@ return data +@pytest.fixture(scope="function") +def sha1(): + """Fixture returning a valid hexadecimal sha1 value. + """ + return random_sha1() + + +@pytest.fixture(scope="function") +def invalid_sha1(): + """Fixture returning an invalid sha1 representation. + """ + return hash_to_hex(bytes(random.randint(0, 255) for _ in range(50))) + + +@pytest.fixture(scope="function") +def sha256(): + """Fixture returning a valid hexadecimal sha256 value. + """ + return random_sha256() + + def _known_swh_objects(tests_data, object_type): return tests_data[object_type] @@ -186,6 +213,36 @@ ) +def _new_content(tests_data): + while True: + new_content = random_content() + sha1_bytes = hash_to_bytes(new_content["sha1"]) + if tests_data["storage"].content_get_data(sha1_bytes) is None: + return new_content + + +@pytest.fixture(scope="function") +def unknown_content(tests_data): + """Fixture returning a random content not ingested into the test archive. + """ + return _new_content(tests_data) + + +@pytest.fixture(scope="function") +def unknown_contents(tests_data): + """Fixture returning random contents not ingested into the test archive. + """ + new_contents = [] + new_content_ids = set() + nb_contents = random.randint(2, 8) + while len(new_contents) != nb_contents: + new_content = _new_content(tests_data) + if new_content["sha1"] not in new_content_ids: + new_contents.append(new_content) + new_content_ids.add(new_content["sha1"]) + return list(new_contents) + + @pytest.fixture(scope="function") def empty_content(): """Fixture returning the empty content ingested into the test archive. @@ -381,6 +438,17 @@ return _directory_with_entry_type(tests_data, "file") +@pytest.fixture(scope="function") +def unknown_directory(tests_data): + """Fixture returning a random directory not ingested into the test archive. + """ + while True: + new_directory = random_sha1() + sha1_bytes = hash_to_bytes(new_directory) + if list(tests_data["storage"].directory_missing([sha1_bytes])): + return new_directory + + @pytest.fixture(scope="function") def empty_directory(): """Fixture returning the empty directory ingested into the test archive. @@ -415,6 +483,17 @@ return gen_revisions_list +@pytest.fixture(scope="function") +def unknown_revision(tests_data): + """Fixture returning a random revision not ingested into the test archive. + """ + while True: + new_revision = random_sha1() + sha1_bytes = hash_to_bytes(new_revision) + if tests_data["storage"].revision_get([sha1_bytes])[0] is None: + return new_revision + + def _get_origin_dfs_revisions_walker(tests_data): storage = tests_data["storage"] origin = random.choice(tests_data["origins"][:-1]) @@ -520,6 +599,17 @@ ) +@pytest.fixture(scope="function") +def unknown_release(tests_data): + """Fixture returning a random release not ingested into the test archive. + """ + while True: + new_release = random_sha1() + sha1_bytes = hash_to_bytes(new_release) + if tests_data["storage"].release_get([sha1_bytes])[0] is None: + return new_release + + @pytest.fixture(scope="function") def snapshot(tests_data): """Fixture returning a random snapshot ingested into the test archive. @@ -527,6 +617,17 @@ return random.choice(_known_swh_objects(tests_data, "snapshots")) +@pytest.fixture(scope="function") +def unknown_snapshot(tests_data): + """Fixture returning a random snapshot not ingested into the test archive. + """ + while True: + new_snapshot = random_sha1() + sha1_bytes = hash_to_bytes(new_snapshot) + if tests_data["storage"].snapshot_get_branches(sha1_bytes) is None: + return new_snapshot + + @pytest.fixture(scope="function") def origin(tests_data): """Fixture returning a random origin ingested into the test archive. diff --git a/swh/web/tests/misc/test_badges.py b/swh/web/tests/misc/test_badges.py --- a/swh/web/tests/misc/test_badges.py +++ b/swh/web/tests/misc/test_badges.py @@ -13,15 +13,7 @@ from swh.web.common.utils import reverse from swh.web.misc.badges import _badge_config, _get_logo_data from swh.web.tests.django_asserts import assert_contains -from swh.web.tests.strategies import ( - invalid_sha1, - new_origin, - unknown_content, - unknown_directory, - unknown_release, - unknown_revision, - unknown_snapshot, -) +from swh.web.tests.strategies import new_origin from swh.web.tests.utils import check_http_get_response @@ -49,24 +41,16 @@ _test_badge_endpoints(client, "snapshot", snapshot) -@given( - unknown_content(), - unknown_directory(), - new_origin(), - unknown_release(), - unknown_revision(), - unknown_snapshot(), - invalid_sha1(), -) +@given(new_origin(),) def test_badge_errors( client, unknown_content, unknown_directory, - new_origin, unknown_release, unknown_revision, unknown_snapshot, invalid_sha1, + new_origin, ): for object_type, object_id in ( ("content", unknown_content["sha1_git"]), diff --git a/swh/web/tests/misc/test_iframe.py b/swh/web/tests/misc/test_iframe.py --- a/swh/web/tests/misc/test_iframe.py +++ b/swh/web/tests/misc/test_iframe.py @@ -3,12 +3,10 @@ # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information -from hypothesis import given from swh.model.hashutil import hash_to_bytes from swh.model.swhids import CoreSWHID, ObjectType from swh.web.common.utils import reverse -from swh.web.tests.strategies import unknown_directory from swh.web.tests.utils import check_html_get_response @@ -53,7 +51,6 @@ ) -@given(unknown_directory()) def test_iframe_object_not_found(client, unknown_directory): swhid = CoreSWHID( object_type=ObjectType.DIRECTORY, object_id=hash_to_bytes(unknown_directory) diff --git a/swh/web/tests/strategies.py b/swh/web/tests/strategies.py --- a/swh/web/tests/strategies.py +++ b/swh/web/tests/strategies.py @@ -4,134 +4,36 @@ # See top-level LICENSE file for more information from datetime import datetime -import random -from hypothesis import assume, settings from hypothesis.extra.dateutil import timezones -from hypothesis.strategies import binary, characters, composite, datetimes, lists, text +from hypothesis.strategies import composite, datetimes, lists, text -from swh.model.hashutil import hash_to_bytes, hash_to_hex from swh.model.hypothesis_strategies import origins as new_origin_strategy +from swh.model.hypothesis_strategies import persons as new_person_strategy +from swh.model.hypothesis_strategies import sha1_git from swh.model.hypothesis_strategies import snapshots as new_snapshot -from swh.model.model import Person, Revision, RevisionType, TimestampWithTimezone -from swh.web.tests.data import get_tests_data +from swh.model.model import Revision, RevisionType, TimestampWithTimezone # Module dedicated to the generation of input data for tests through # the use of hypothesis. -# Some of these data are sampled from a test archive created and populated -# in the swh.web.tests.data module. - -# Set the swh-web hypothesis profile if none has been explicitly set -hypothesis_default_settings = settings.get_profile("default") -if repr(settings()) == repr(hypothesis_default_settings): - settings.load_profile("swh-web") - - -def sha1(): - """ - Hypothesis strategy returning a valid hexadecimal sha1 value. - """ - return binary(min_size=20, max_size=20).map(hash_to_hex) - - -def invalid_sha1(): - """ - Hypothesis strategy returning an invalid sha1 representation. - """ - return binary(min_size=50, max_size=50).map(hash_to_hex) - - -def sha256(): - """ - Hypothesis strategy returning a valid hexadecimal sha256 value. - """ - return binary(min_size=32, max_size=32).map(hash_to_hex) - - -@composite -def new_content(draw): - blake2s256_hex = draw(sha256()) - sha1_hex = draw(sha1()) - sha1_git_hex = draw(sha1()) - sha256_hex = draw(sha256()) - - assume(sha1_hex != sha1_git_hex) - assume(blake2s256_hex != sha256_hex) - - return { - "blake2S256": blake2s256_hex, - "sha1": sha1_hex, - "sha1_git": sha1_git_hex, - "sha256": sha256_hex, - } - - -def unknown_content(): - """ - Hypothesis strategy returning a random content not ingested - into the test archive. - """ - return new_content().filter( - lambda c: get_tests_data()["storage"].content_get_data(hash_to_bytes(c["sha1"])) - is None - ) - - -def unknown_contents(): - """ - Hypothesis strategy returning random contents not ingested - into the test archive. - """ - return lists(unknown_content(), min_size=2, max_size=8) - - -def unknown_directory(): - """ - Hypothesis strategy returning a random directory not ingested - into the test archive. - """ - return sha1().filter( - lambda s: len( - list(get_tests_data()["storage"].directory_missing([hash_to_bytes(s)])) - ) - > 0 - ) def new_origin(): - """ - Hypothesis strategy returning a random origin not ingested + """Hypothesis strategy returning a random origin not ingested into the test archive. """ return new_origin_strategy() -def new_origins(nb_origins=None): - """ - Hypothesis strategy returning random origins not ingested - into the test archive. - """ - min_size = nb_origins if nb_origins is not None else 2 - max_size = nb_origins if nb_origins is not None else 8 - size = random.randint(min_size, max_size) - return lists( - new_origin(), - min_size=size, - max_size=size, - unique_by=lambda o: tuple(sorted(o.items())), - ) - - def visit_dates(nb_dates=None): - """ - Hypothesis strategy returning a list of visit dates. + """Hypothesis strategy returning a list of visit dates. """ min_size = nb_dates if nb_dates else 2 max_size = nb_dates if nb_dates else 8 return lists( datetimes( min_value=datetime(2015, 1, 1, 0, 0), - max_value=datetime(2018, 12, 31, 0, 0), + max_value=datetime.now(), timezones=timezones(), ), min_size=min_size, @@ -140,56 +42,20 @@ ).map(sorted) -def unknown_release(): - """ - Hypothesis strategy returning a random revision not ingested - into the test archive. - """ - return sha1().filter( - lambda s: get_tests_data()["storage"].release_get([s])[0] is None - ) - - -def unknown_revision(): - """ - Hypothesis strategy returning a random revision not ingested - into the test archive. +def new_person(): + """Hypothesis strategy returning random raw swh person data. """ - return sha1().filter( - lambda s: get_tests_data()["storage"].revision_get([hash_to_bytes(s)])[0] - is None - ) - - -@composite -def new_person(draw): - """ - Hypothesis strategy returning random raw swh person data. - """ - name = draw( - text( - min_size=5, - max_size=30, - alphabet=characters(min_codepoint=0, max_codepoint=255), - ) - ) - email = "%s@company.org" % name - return Person( - name=name.encode(), - email=email.encode(), - fullname=("%s <%s>" % (name, email)).encode(), - ) + return new_person_strategy() @composite def new_swh_date(draw): - """ - Hypothesis strategy returning random raw swh date data. + """Hypothesis strategy returning random raw swh date data. """ timestamp = draw( - datetimes( - min_value=datetime(2015, 1, 1, 0, 0), max_value=datetime(2018, 12, 31, 0, 0) - ).map(lambda d: int(d.timestamp())) + datetimes(min_value=datetime(2015, 1, 1, 0, 0), max_value=datetime.now()).map( + lambda d: int(d.timestamp()) + ) ) return { "timestamp": timestamp, @@ -200,12 +66,11 @@ @composite def new_revision(draw): - """ - Hypothesis strategy returning random raw swh revision data + """Hypothesis strategy returning random raw swh revision data not ingested into the test archive. """ return Revision( - directory=draw(sha1().map(hash_to_bytes)), + directory=draw(sha1_git()), author=draw(new_person()), committer=draw(new_person()), message=draw(text(min_size=20, max_size=100).map(lambda t: t.encode())), @@ -216,14 +81,6 @@ ) -def unknown_revisions(min_size=2, max_size=8): - """ - Hypothesis strategy returning random revisions not ingested - into the test archive. - """ - return lists(unknown_revision(), min_size=min_size, max_size=max_size) - - def new_snapshots(nb_snapshots=None): min_size = nb_snapshots if nb_snapshots else 2 max_size = nb_snapshots if nb_snapshots else 8 @@ -232,14 +89,3 @@ min_size=min_size, max_size=max_size, ) - - -def unknown_snapshot(): - """ - Hypothesis strategy returning a random revision not ingested - into the test archive. - """ - return sha1().filter( - lambda s: get_tests_data()["storage"].snapshot_get_branches(hash_to_bytes(s)) - is None - )