Skip to content

Commit 0ffc54d

Browse files
committed
Add tests about link hashes validation
1 parent 42b19ab commit 0ffc54d

File tree

1 file changed

+97
-0
lines changed

1 file changed

+97
-0
lines changed

tests/functional/test_install.py

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import hashlib
12
import os
23
import re
34
import ssl
@@ -13,6 +14,7 @@
1314
from pip._internal.cli.status_codes import ERROR, SUCCESS
1415
from pip._internal.models.index import PyPI, TestPyPI
1516
from pip._internal.utils.misc import rmtree
17+
from pip._internal.utils.urls import path_to_url
1618
from tests.conftest import CertFactory
1719
from tests.lib import (
1820
PipTestEnvironment,
@@ -616,6 +618,101 @@ def test_hashed_install_failure(script: PipTestEnvironment, tmpdir: Path) -> Non
616618
assert len(result.files_created) == 0
617619

618620

621+
def test_link_hash_pass_require_hashes(
622+
script: PipTestEnvironment, shared_data: TestData
623+
) -> None:
624+
"""Test that a good hash in user provided direct URL is
625+
considered valid for --require-hashes."""
626+
url = path_to_url(str(shared_data.packages.joinpath("simple-1.0.tar.gz")))
627+
url = (
628+
f"{url}#sha256="
629+
"393043e672415891885c9a2a0929b1af95fb866d6ca016b42d2e6ce53619b653"
630+
)
631+
script.pip_install_local("--no-deps", "--require-hashes", url)
632+
633+
634+
def test_bad_link_hash_install_failure(
635+
script: PipTestEnvironment, shared_data: TestData
636+
) -> None:
637+
"""Test that wrong hash in direct URL stop installation."""
638+
url = path_to_url(str(shared_data.packages.joinpath("simple-1.0.tar.gz")))
639+
url = f"{url}#sha256=invalidhash"
640+
result = script.pip_install_local("--no-deps", url, expect_error=True)
641+
assert "THESE PACKAGES DO NOT MATCH THE HASHES" in result.stderr
642+
643+
644+
def test_link_hash_in_dep_fails_require_hashes(
645+
script: PipTestEnvironment, tmp_path: Path, shared_data: TestData
646+
) -> None:
647+
"""Test that a good hash in direct URL dependency is not considered
648+
for --require-hashes."""
649+
# Create a project named pkga that depends on the simple-1.0.tar.gz with a direct
650+
# URL including a hash.
651+
simple_url = path_to_url(str(shared_data.packages.joinpath("simple-1.0.tar.gz")))
652+
simple_url_with_hash = (
653+
f"{simple_url}#sha256="
654+
"393043e672415891885c9a2a0929b1af95fb866d6ca016b42d2e6ce53619b653"
655+
)
656+
project_path = tmp_path / "pkga"
657+
project_path.mkdir()
658+
project_path.joinpath("pyproject.toml").write_text(
659+
textwrap.dedent(
660+
f"""\
661+
[project]
662+
name = "pkga"
663+
version = "1.0"
664+
dependencies = ["simple @ {simple_url_with_hash}"]
665+
"""
666+
)
667+
)
668+
# Build a wheel for pkga and compute its hash.
669+
wheelhouse = tmp_path / "wheehouse"
670+
wheelhouse.mkdir()
671+
script.pip("wheel", "--no-deps", "-w", wheelhouse, project_path)
672+
digest = hashlib.sha256(
673+
wheelhouse.joinpath("pkga-1.0-py3-none-any.whl").read_bytes()
674+
).hexdigest()
675+
# Install pkga from a requirements file with hash, using --require-hashes.
676+
# This should fail because we have not provided a hash for the 'simple' dependency.
677+
with requirements_file(f"pkga==1.0 --hash sha256:{digest}", tmp_path) as reqs_file:
678+
result = script.pip(
679+
"install",
680+
"--no-build-isolation",
681+
"--require-hashes",
682+
"--no-index",
683+
"-f",
684+
wheelhouse,
685+
"-r",
686+
reqs_file,
687+
expect_error=True,
688+
)
689+
assert "Hashes are required in --require-hashes mode" in result.stderr
690+
691+
692+
def test_bad_link_hash_in_dep_install_failure(
693+
script: PipTestEnvironment, tmp_path: Path, shared_data: TestData
694+
) -> None:
695+
"""Test that wrong hash in direct URL dependency stops installation."""
696+
url = path_to_url(str(shared_data.packages.joinpath("simple-1.0.tar.gz")))
697+
url = f"{url}#sha256=invalidhash"
698+
project_path = tmp_path / "pkga"
699+
project_path.mkdir()
700+
project_path.joinpath("pyproject.toml").write_text(
701+
textwrap.dedent(
702+
f"""\
703+
[project]
704+
name = "pkga"
705+
version = "1.0"
706+
dependencies = ["simple @ {url}"]
707+
"""
708+
)
709+
)
710+
result = script.pip_install_local(
711+
"--no-build-isolation", project_path, expect_error=True
712+
)
713+
assert "THESE PACKAGES DO NOT MATCH THE HASHES" in result.stderr, result.stderr
714+
715+
619716
def assert_re_match(pattern: str, text: str) -> None:
620717
assert re.search(pattern, text), f"Could not find {pattern!r} in {text!r}"
621718

0 commit comments

Comments
 (0)