Exemple #1
0
 def test_get_applicable_candidates__hashes(
     self,
     specifier,
     expected_versions,
 ):
     """
     Test a non-None hashes value.
     """
     candidates = [
         make_mock_candidate('1.0'),
         make_mock_candidate('1.1', hex_digest=(64 * 'a')),
         make_mock_candidate('1.2', hex_digest=(64 * 'b')),
     ]
     hashes_data = {
         'sha256': [64 * 'b'],
     }
     hashes = Hashes(hashes_data)
     evaluator = CandidateEvaluator.create(
         'my-project',
         specifier=specifier,
         hashes=hashes,
     )
     actual = evaluator.get_applicable_candidates(candidates)
     actual_versions = [str(c.version) for c in actual]
     assert actual_versions == expected_versions
Exemple #2
0
 def test_get_applicable_candidates__hashes(
     self,
     specifier: SpecifierSet,
     expected_versions: List[str],
 ) -> None:
     """
     Test a non-None hashes value.
     """
     candidates = [
         make_mock_candidate("1.0"),
         make_mock_candidate("1.1", hex_digest=(64 * "a")),
         make_mock_candidate("1.2", hex_digest=(64 * "b")),
     ]
     hashes_data = {
         "sha256": [64 * "b"],
     }
     hashes = Hashes(hashes_data)
     evaluator = CandidateEvaluator.create(
         "my-project",
         specifier=specifier,
         hashes=hashes,
     )
     actual = evaluator.get_applicable_candidates(candidates)
     actual_versions = [str(c.version) for c in actual]
     assert actual_versions == expected_versions
Exemple #3
0
    def test_sort_best_candidate__all_yanked(self, caplog, monkeypatch):
        """
        Test all candidates yanked.
        """
        # Ignore spurious DEBUG level messages
        # TODO: Probably better to work out why they are occurring, but IMO the
        #       tests are at fault here for being to dependent on exact output.
        caplog.set_level(logging.WARNING)
        candidates = [
            make_mock_candidate('1.0', yanked_reason='bad metadata #1'),
            # Put the best candidate in the middle, to test sorting.
            make_mock_candidate('3.0', yanked_reason='bad metadata #3'),
            make_mock_candidate('2.0', yanked_reason='bad metadata #2'),
        ]
        ireq = install_req_from_line("pkg")

        resolver = self._make_test_resolver(monkeypatch, candidates)
        resolver._populate_link(ireq)

        assert ireq.link == candidates[1].link

        # Check the log messages.
        assert len(caplog.records) == 1
        record = caplog.records[0]
        assert record.levelname == 'WARNING'
        assert record.message == (
            'The candidate selected for download or install is a yanked '
            "version: 'mypackage' candidate "
            '(version 3.0 at https://example.com/pkg-3.0.tar.gz)\n'
            'Reason for being yanked: bad metadata #3')
Exemple #4
0
    def test_sort_best_candidate__all_yanked(self, caplog, monkeypatch):
        """
        Test all candidates yanked.
        """
        candidates = [
            make_mock_candidate('1.0', yanked_reason='bad metadata #1'),
            # Put the best candidate in the middle, to test sorting.
            make_mock_candidate('3.0', yanked_reason='bad metadata #3'),
            make_mock_candidate('2.0', yanked_reason='bad metadata #2'),
        ]
        ireq = install_req_from_line("pkg")

        resolver = self._make_test_resolver(monkeypatch, candidates)
        resolver._populate_link(ireq)

        assert ireq.link == candidates[1].link

        # Check the log messages.
        assert len(caplog.records) == 1
        record = caplog.records[0]
        assert record.levelname == 'WARNING'
        assert record.message == (
            'The candidate selected for download or install is a yanked '
            "version: 'mypackage' candidate "
            '(version 3.0 at https://example.com/pkg-3.0.tar.gz)\n'
            'Reason for being yanked: bad metadata #3'
        )
Exemple #5
0
def test_filter_unallowed_hashes__log_message_with_no_match(
    caplog: pytest.LogCaptureFixture,
) -> None:
    caplog.set_level(logging.DEBUG)

    candidates = [
        make_mock_candidate("1.0"),
        make_mock_candidate("1.1", hex_digest=(64 * "b")),
        make_mock_candidate("1.2", hex_digest=(64 * "c")),
    ]
    hashes_data = {
        "sha256": [64 * "a", 64 * "d"],
    }
    hashes = Hashes(hashes_data)
    actual = filter_unallowed_hashes(
        candidates,
        hashes=hashes,
        project_name="my-project",
    )
    assert len(actual) == 3

    expected_message = (
        "Checked 3 links for project 'my-project' against 2 hashes "
        "(0 matches, 1 no digest): discarding no candidates"
    )
    check_caplog(caplog, "DEBUG", expected_message)
Exemple #6
0
    def test_sort_best_candidate__has_non_yanked(self, caplog, monkeypatch):
        """
        Test unyanked candidate preferred over yanked.
        """
        candidates = [
            make_mock_candidate('1.0'),
            make_mock_candidate('2.0', yanked_reason='bad metadata #2'),
        ]
        ireq = install_req_from_line("pkg")

        resolver = self._make_test_resolver(monkeypatch, candidates)
        resolver._populate_link(ireq)

        assert ireq.link == candidates[0].link
        assert len(caplog.records) == 0
Exemple #7
0
    def test_sort_best_candidate__yanked_reason(
        self,
        caplog,
        monkeypatch,
        yanked_reason,
        expected_reason,
    ):
        """
        Test the log message with various reason strings.
        """
        # Ignore spurious DEBUG level messages
        # TODO: Probably better to work out why they are occurring, but IMO the
        #       tests are at fault here for being to dependent on exact output.
        caplog.set_level(logging.WARNING)
        candidates = [
            make_mock_candidate('1.0', yanked_reason=yanked_reason),
        ]
        ireq = install_req_from_line("pkg")

        resolver = self._make_test_resolver(monkeypatch, candidates)
        resolver._populate_link(ireq)

        assert ireq.link == candidates[0].link

        assert len(caplog.records) == 1
        record = caplog.records[0]
        assert record.levelname == 'WARNING'
        expected_message = (
            'The candidate selected for download or install is a yanked '
            "version: 'mypackage' candidate "
            '(version 1.0 at https://example.com/pkg-1.0.tar.gz)\n'
            'Reason for being yanked: ') + expected_reason
        assert record.message == expected_message
Exemple #8
0
    def test_sort_best_candidate__yanked_reason(
        self, caplog, monkeypatch, yanked_reason, expected_reason,
    ):
        """
        Test the log message with various reason strings.
        """
        candidates = [
            make_mock_candidate('1.0', yanked_reason=yanked_reason),
        ]
        ireq = install_req_from_line("pkg")

        resolver = self._make_test_resolver(monkeypatch, candidates)
        resolver._populate_link(ireq)

        assert ireq.link == candidates[0].link

        assert len(caplog.records) == 1
        record = caplog.records[0]
        assert record.levelname == 'WARNING'
        expected_message = (
            'The candidate selected for download or install is a yanked '
            "version: 'mypackage' candidate "
            '(version 1.0 at https://example.com/pkg-1.0.tar.gz)\n'
            'Reason for being yanked: '
        ) + expected_reason
        assert record.message == expected_message
Exemple #9
0
def test_filter_unallowed_hashes(hex_digest, expected_versions):
    candidates = [
        make_mock_candidate('1.0'),
        make_mock_candidate('1.1', hex_digest=(64 * 'a')),
        make_mock_candidate('1.2', hex_digest=(64 * 'b')),
    ]
    hashes_data = {
        'sha256': [hex_digest],
    }
    hashes = Hashes(hashes_data)
    actual = filter_unallowed_hashes(
        candidates, hashes=hashes, project_name='my-project',
    )

    actual_versions = [str(candidate.version) for candidate in actual]
    assert actual_versions == expected_versions
    # Check that the return value is always different from the given value.
    assert actual is not candidates
Exemple #10
0
 def test_sort_key__is_yanked(self, yanked_reason, expected):
     """
     Test the effect of is_yanked on _sort_key()'s return value.
     """
     candidate = make_mock_candidate('1.0', yanked_reason=yanked_reason)
     evaluator = CandidateEvaluator.create('my-project')
     sort_value = evaluator._sort_key(candidate)
     # Yanked / non-yanked is reflected in the second element of the tuple.
     actual = sort_value[1]
     assert actual == expected
Exemple #11
0
    def test_sort_best_candidate__has_non_yanked(self, caplog, monkeypatch):
        """
        Test unyanked candidate preferred over yanked.
        """
        # Ignore spurious DEBUG level messages
        # TODO: Probably better to work out why they are occurring, but IMO the
        #       tests are at fault here for being to dependent on exact output.
        caplog.set_level(logging.WARNING)
        candidates = [
            make_mock_candidate('1.0'),
            make_mock_candidate('2.0', yanked_reason='bad metadata #2'),
        ]
        ireq = install_req_from_line("pkg")

        resolver = self._make_test_resolver(monkeypatch, candidates)
        resolver._populate_link(ireq)

        assert ireq.link == candidates[0].link
        assert len(caplog.records) == 0
Exemple #12
0
def test_filter_unallowed_hashes(hex_digest: str, expected_versions: List[str]) -> None:
    candidates = [
        make_mock_candidate("1.0"),
        make_mock_candidate("1.1", hex_digest=(64 * "a")),
        make_mock_candidate("1.2", hex_digest=(64 * "b")),
    ]
    hashes_data = {
        "sha256": [hex_digest],
    }
    hashes = Hashes(hashes_data)
    actual = filter_unallowed_hashes(
        candidates,
        hashes=hashes,
        project_name="my-project",
    )

    actual_versions = [str(candidate.version) for candidate in actual]
    assert actual_versions == expected_versions
    # Check that the return value is always different from the given value.
    assert actual is not candidates
Exemple #13
0
def test_filter_unallowed_hashes__no_hashes(caplog):
    caplog.set_level(logging.DEBUG)

    candidates = [
        make_mock_candidate('1.0'),
        make_mock_candidate('1.1'),
    ]
    actual = filter_unallowed_hashes(
        candidates, hashes=Hashes(), project_name='my-project',
    )

    # Check that the return value is a copy.
    assert actual == candidates
    assert actual is not candidates

    expected_message = (
        "Given no hashes to check 2 links for project 'my-project': "
        "discarding no candidates"
    )
    check_caplog(caplog, 'DEBUG', expected_message)
Exemple #14
0
 def test_sort_key__is_yanked(self, yanked_reason: Optional[str],
                              expected: int) -> None:
     """
     Test the effect of is_yanked on _sort_key()'s return value.
     """
     candidate = make_mock_candidate("1.0", yanked_reason=yanked_reason)
     evaluator = CandidateEvaluator.create("my-project")
     sort_value = evaluator._sort_key(candidate)
     # Yanked / non-yanked is reflected in the second element of the tuple.
     actual = sort_value[1]
     assert actual == expected
Exemple #15
0
def test_filter_unallowed_hashes__log_message_with_match(
    caplog: pytest.LogCaptureFixture, ) -> None:
    caplog.set_level(logging.DEBUG)

    # Test 1 match, 2 non-matches, 3 no hashes so all 3 values will be
    # different.
    candidates = [
        make_mock_candidate("1.0"),
        make_mock_candidate("1.1", ),
        make_mock_candidate("1.2", ),
        make_mock_candidate("1.3", hex_digest=(64 * "a")),
        make_mock_candidate("1.4", hex_digest=(64 * "b")),
        make_mock_candidate("1.5", hex_digest=(64 * "c")),
    ]
    hashes_data = {
        "sha256": [64 * "a", 64 * "d"],
    }
    hashes = Hashes(hashes_data)
    actual = filter_unallowed_hashes(
        candidates,
        hashes=hashes,
        project_name="my-project",
    )
    assert len(actual) == 4

    expected_message = (
        "Checked 6 links for project 'my-project' against 2 hashes "
        "(1 matches, 3 no digest): discarding 2 non-matches:\n"
        "  https://example.com/pkg-1.4.tar.gz#sha256="
        "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n"
        "  https://example.com/pkg-1.5.tar.gz#sha256="
        "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc")
    check_caplog(caplog, "DEBUG", expected_message)
Exemple #16
0
def test_filter_unallowed_hashes__log_message_with_match(caplog):
    caplog.set_level(logging.DEBUG)

    # Test 1 match, 2 non-matches, 3 no hashes so all 3 values will be
    # different.
    candidates = [
        make_mock_candidate('1.0'),
        make_mock_candidate('1.1',),
        make_mock_candidate('1.2',),
        make_mock_candidate('1.3', hex_digest=(64 * 'a')),
        make_mock_candidate('1.4', hex_digest=(64 * 'b')),
        make_mock_candidate('1.5', hex_digest=(64 * 'c')),
    ]
    hashes_data = {
        'sha256': [64 * 'a', 64 * 'd'],
    }
    hashes = Hashes(hashes_data)
    actual = filter_unallowed_hashes(
        candidates, hashes=hashes, project_name='my-project',
    )
    assert len(actual) == 4

    expected_message = (
        "Checked 6 links for project 'my-project' against 2 hashes "
        "(1 matches, 3 no digest): discarding 2 non-matches:\n"
        "  https://example.com/pkg-1.4.tar.gz#sha256="
        "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n"
        "  https://example.com/pkg-1.5.tar.gz#sha256="
        "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
    )
    check_caplog(caplog, 'DEBUG', expected_message)
Exemple #17
0
def test_filter_unallowed_hashes__no_hashes(
        caplog: pytest.LogCaptureFixture) -> None:
    caplog.set_level(logging.DEBUG)

    candidates = [
        make_mock_candidate("1.0"),
        make_mock_candidate("1.1"),
    ]
    actual = filter_unallowed_hashes(
        candidates,
        hashes=Hashes(),
        project_name="my-project",
    )

    # Check that the return value is a copy.
    assert actual == candidates
    assert actual is not candidates

    expected_message = (
        "Given no hashes to check 2 links for project 'my-project': "
        "discarding no candidates")
    check_caplog(caplog, "DEBUG", expected_message)
Exemple #18
0
    def test_sort_best_candidate__best_yanked_but_not_all(
        self, caplog,
    ):
        """
        Test the best candidates being yanked, but not all.
        """
        caplog.set_level(logging.INFO)
        candidates = [
            make_mock_candidate('4.0', yanked_reason='bad metadata #4'),
            # Put the best candidate in the middle, to test sorting.
            make_mock_candidate('2.0'),
            make_mock_candidate('3.0', yanked_reason='bad metadata #3'),
            make_mock_candidate('1.0'),
        ]
        expected_best = candidates[1]
        evaluator = CandidateEvaluator.create('my-project')
        actual = evaluator.sort_best_candidate(candidates)
        assert actual is expected_best
        assert str(actual.version) == '2.0'

        # Check the log messages.
        assert len(caplog.records) == 0
Exemple #19
0
def test_filter_unallowed_hashes__log_message_with_no_match(caplog):
    caplog.set_level(logging.DEBUG)

    candidates = [
        make_mock_candidate('1.0'),
        make_mock_candidate('1.1', hex_digest=(64 * 'b')),
        make_mock_candidate('1.2', hex_digest=(64 * 'c')),
    ]
    hashes_data = {
        'sha256': [64 * 'a', 64 * 'd'],
    }
    hashes = Hashes(hashes_data)
    actual = filter_unallowed_hashes(
        candidates, hashes=hashes, project_name='my-project',
    )
    assert len(actual) == 3

    expected_message = (
        "Checked 3 links for project 'my-project' against 2 hashes "
        "(0 matches, 1 no digest): discarding no candidates"
    )
    check_caplog(caplog, 'DEBUG', expected_message)
Exemple #20
0
    def test_sort_best_candidate__best_yanked_but_not_all(
        self,
        caplog: pytest.LogCaptureFixture,
    ) -> None:
        """
        Test the best candidates being yanked, but not all.
        """
        caplog.set_level(logging.INFO)
        candidates = [
            make_mock_candidate("4.0", yanked_reason="bad metadata #4"),
            # Put the best candidate in the middle, to test sorting.
            make_mock_candidate("2.0"),
            make_mock_candidate("3.0", yanked_reason="bad metadata #3"),
            make_mock_candidate("1.0"),
        ]
        expected_best = candidates[1]
        evaluator = CandidateEvaluator.create("my-project")
        actual = evaluator.sort_best_candidate(candidates)
        assert actual is expected_best
        assert str(actual.version) == "2.0"

        # Check the log messages.
        assert len(caplog.records) == 0
Exemple #21
0
 def test_sort_key__hash(self, hex_digest: Optional[str], expected: int) -> None:
     """
     Test the effect of the link's hash on _sort_key()'s return value.
     """
     candidate = make_mock_candidate("1.0", hex_digest=hex_digest)
     hashes_data = {
         "sha256": [64 * "a"],
     }
     hashes = Hashes(hashes_data)
     evaluator = CandidateEvaluator.create("my-project", hashes=hashes)
     sort_value = evaluator._sort_key(candidate)
     # The hash is reflected in the first element of the tuple.
     actual = sort_value[0]
     assert actual == expected
Exemple #22
0
 def test_sort_key__hash(self, hex_digest, expected):
     """
     Test the effect of the link's hash on _sort_key()'s return value.
     """
     candidate = make_mock_candidate('1.0', hex_digest=hex_digest)
     hashes_data = {
         'sha256': [64 * 'a'],
     }
     hashes = Hashes(hashes_data)
     evaluator = CandidateEvaluator.create('my-project', hashes=hashes)
     sort_value = evaluator._sort_key(candidate)
     # The hash is reflected in the first element of the tuple.
     actual = sort_value[0]
     assert actual == expected
Exemple #23
0
 def test_get_applicable_candidates(self):
     specifier = SpecifierSet('<= 1.11')
     versions = ['1.10', '1.11', '1.12']
     candidates = [make_mock_candidate(version) for version in versions]
     evaluator = CandidateEvaluator.create(
         'my-project',
         specifier=specifier,
     )
     actual = evaluator.get_applicable_candidates(candidates)
     expected_applicable = candidates[:2]
     assert [str(c.version) for c in expected_applicable] == [
         '1.10',
         '1.11',
     ]
     assert actual == expected_applicable
Exemple #24
0
 def test_get_applicable_candidates(self) -> None:
     specifier = SpecifierSet("<= 1.11")
     versions = ["1.10", "1.11", "1.12"]
     candidates = [make_mock_candidate(version) for version in versions]
     evaluator = CandidateEvaluator.create(
         "my-project",
         specifier=specifier,
     )
     actual = evaluator.get_applicable_candidates(candidates)
     expected_applicable = candidates[:2]
     assert [str(c.version) for c in expected_applicable] == [
         "1.10",
         "1.11",
     ]
     assert actual == expected_applicable
Exemple #25
0
    def test_compute_best_candidate__none_best(self):
        """
        Test returning a None best candidate.
        """
        specifier = SpecifierSet('<= 1.10')
        versions = ['1.11', '1.12']
        candidates = [make_mock_candidate(version) for version in versions]
        evaluator = CandidateEvaluator.create(
            'my-project',
            specifier=specifier,
        )
        result = evaluator.compute_best_candidate(candidates)

        assert result._candidates == candidates
        assert result._applicable_candidates == []
        assert result.best_candidate is None
Exemple #26
0
    def test_compute_best_candidate__none_best(self) -> None:
        """
        Test returning a None best candidate.
        """
        specifier = SpecifierSet("<= 1.10")
        versions = ["1.11", "1.12"]
        candidates = [make_mock_candidate(version) for version in versions]
        evaluator = CandidateEvaluator.create(
            "my-project",
            specifier=specifier,
        )
        result = evaluator.compute_best_candidate(candidates)

        assert result._candidates == candidates
        assert result._applicable_candidates == []
        assert result.best_candidate is None
Exemple #27
0
    def test_compute_best_candidate(self):
        specifier = SpecifierSet('<= 1.11')
        versions = ['1.10', '1.11', '1.12']
        candidates = [make_mock_candidate(version) for version in versions]
        evaluator = CandidateEvaluator.create(
            'my-project',
            specifier=specifier,
        )
        result = evaluator.compute_best_candidate(candidates)

        assert result._candidates == candidates
        expected_applicable = candidates[:2]
        assert [str(c.version) for c in expected_applicable] == [
            '1.10',
            '1.11',
        ]
        assert result._applicable_candidates == expected_applicable

        assert result.best_candidate is expected_applicable[1]
Exemple #28
0
    def test_compute_best_candidate(self) -> None:
        specifier = SpecifierSet("<= 1.11")
        versions = ["1.10", "1.11", "1.12"]
        candidates = [make_mock_candidate(version) for version in versions]
        evaluator = CandidateEvaluator.create(
            "my-project",
            specifier=specifier,
        )
        result = evaluator.compute_best_candidate(candidates)

        assert result._candidates == candidates
        expected_applicable = candidates[:2]
        assert [str(c.version) for c in expected_applicable] == [
            "1.10",
            "1.11",
        ]
        assert result._applicable_candidates == expected_applicable

        assert result.best_candidate is expected_applicable[1]