Files
lix/tests/functional2/commands/test_hash.py
T
Rebecca Turnerandrootile cb34b56fea tests/functional2: Fix Python LSP by adjusting imports
See: cl/4840

When importing Python modules, we include `functional2` in the module
path, like this:

    from functional2.testlib.fixtures.env import ManagedEnv

This means that python expects to see a file like
`functional2/testlib/fixtures/env.py`. We run `pytest` from `tests/` in
the `justfile` and have `tests/functional2/__init__.py` so `pytest` in
`meson` is able to find these imports.

However, language servers generally consider the `pyproject.toml` to be
the project root, so (e.g.) `pyright` is unable to follow any of the
`functional2` imports, leading to lots of spurious errors.

In cl/4840 I moved `tests/functional2/pyproject.toml` to
`tests/pyproject.toml`, which worked but was considered aesthetically
unappealing.

This diff is much larger but it's a more elegant solution.

Change-Id: I2983c7b87f88f59a4e3521451a9f5acd6a6a6964
2026-01-23 15:06:51 +01:00

133 lines
4.6 KiB
Python

from pathlib import Path
from collections.abc import Callable
import pytest
from testlib.fixtures.file_helper import _init_files # noqa: PLC2701
from testlib.fixtures.file_helper import File, AssetSymlink, with_files, Symlink
from testlib.fixtures.nix import Nix
from testlib.fixtures.snapshot import Snapshot
@pytest.mark.parametrize("algo", ["md5", "sha1", "sha256", "sha512"])
@pytest.mark.parametrize(
"content",
["", "a", "abc", "message_digest", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"],
)
@pytest.mark.parametrize("format_flag", ["--base16", "--base32", "--sri"])
@pytest.mark.parametrize("classic", [True, False])
def test_hash(
algo: str,
content: str,
format_flag: str,
classic: bool,
nix: Nix,
snapshot: Callable[[str], Snapshot],
files: Path,
):
_init_files(
{
"vector": File(content),
"expected_hash.txt": AssetSymlink(
f"assets/test_hash/{content}_{algo}_{format_flag}_{classic}.out.exp"
),
},
files,
Path(__file__).parent,
nix.env,
)
args = [format_flag, "--type", algo, files / "vector"]
if classic:
res = nix.nix(["--flat", *args], nix_exe="nix-hash").run().ok()
else:
res = nix.nix(["hash", "file", *args], flake=True).run().ok()
assert snapshot("expected_hash.txt") == res.stdout_s
@with_files({"vector": File("abc")})
def test_hash_classic_defaults_base16(nix: Nix, files: Path):
res = nix.nix(["--flat", "--type", "sha512", files / "vector"], nix_exe="nix-hash").run().ok()
assert (
res.stdout_plain
== "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
)
@with_files({"vector": File("abc")})
def test_hash_command_defaults_sri(nix: Nix, files: Path):
res = nix.nix(["hash", "file", "--type", "sha512", files / "vector"], flake=True).run().ok()
assert (
res.stdout_plain
== "sha512-3a81oZNherrMQXNJriBBMRLm+k6JqX6iCp7u5ktV05ohkpkqJ0/BqDa6PCOj/uu9RU1EI2Q86A4qmslPpUyknw=="
)
@with_files(
{
"hash-part": {
"hello": File("Hello World\n", 0o644) # Default perms
}
}
)
def test_hash_part(nix: Nix, files: Path):
res = nix.nix(["--type", "md5", files / "hash-part"], nix_exe="nix-hash").run().ok()
assert res.stdout_plain == "ea9b55537dd4c7e104515b2ccfaf4100"
@with_files(
{
"hash-part": {
"hello": File("Hello World\n", 0o755) # chmod +x
}
}
)
def test_hash_part_exec_matters(nix: Nix, files: Path):
res = nix.nix(["--type", "md5", files / "hash-part"], nix_exe="nix-hash").run().ok()
assert res.stdout_plain == "20f3ffe011d4cfa7d72bfabef7882836"
@with_files({"hash-part": {"hello": File("Hello World\n", 0o744)}})
def test_hash_part_everything_else_doesnt(nix: Nix, files: Path):
res = nix.nix(["--type", "md5", files / "hash-part"], nix_exe="nix-hash").run().ok()
assert res.stdout_plain == "20f3ffe011d4cfa7d72bfabef7882836"
@with_files({"hash-part": {"hello": Symlink("x")}})
def test_hash_part_filetype_matters(nix: Nix, files: Path):
res = nix.nix(["--type", "md5", files / "hash-part"], nix_exe="nix-hash").run().ok()
assert res.stdout_plain == "f78b733a68f5edbdf9413899339eaa4a"
@pytest.mark.parametrize(
("algo", "orig", "b32", "b64"),
[
(
"sha1",
"800d59cfcd3c05e900cb4e214be48f6b886a08df",
"vw46m23bizj4n8afrc0fj19wrp7mj3c0",
"gA1Zz808BekAy04hS+SPa4hqCN8=",
),
(
"sha256",
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
"1b8m03r63zqhnjf7l5wnldhh7c134ap5vpj0850ymkq1iyzicy5s",
"ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=",
),
(
"sha512",
"204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445",
"12k9jiq29iyqm03swfsgiw5mlqs173qazm3n7daz43infy12pyrcdf30fkk3qwv4yl2ick8yipc2mqnlh48xsvvxl60lbx8vp38yji0",
"IEqPxt2oLwoM7XvrjgikFlfBbvRosiioJ5vjMacDwzWW/RXBOxsH+aodO+pXeJygMa2Fx6cd1wNU7GMSOMo0RQ==",
),
],
)
def test_hash_conversion(algo: str, orig: str, b32: str, b64: str, nix: Nix):
for target_type, exp in zip(
["to-base16", "to-base32", "to-base64", "to-sri"], [orig, b32, b64, f"{algo}-{b64}"]
):
res = nix.nix(["--type", algo, f"--{target_type}", orig], nix_exe="nix-hash").run().ok()
assert res.stdout_plain == exp
res = nix.nix(["hash", target_type, "--type", algo, orig], flake=True).run().ok()
assert res.stdout_plain == exp