condorcore-keyring/tests/test_keyring.py
David Runge 743d2bb3bb
Add tests for introspection and export
libkeyringctl/keyring.py:
Change `get_packets_from_path()` to use full conditional statements
which is easier to cover in tests.

tests/test_keyring.py:
Add simple tests for `get_packets_from_path()`,
`get_packets_from_listing()`, `export()` and `build()`.
2021-11-30 22:54:16 +01:00

292 lines
10 KiB
Python

from contextlib import nullcontext as does_not_raise
from copy import deepcopy
from pathlib import Path
from typing import ContextManager
from unittest.mock import Mock
from unittest.mock import patch
from pytest import mark
from pytest import raises
from libkeyringctl import keyring
from libkeyringctl.types import Fingerprint
from libkeyringctl.types import Uid
from libkeyringctl.types import Username
from .conftest import create_certificate
from .conftest import create_key_revocation
from .conftest import create_uid_certification
from .conftest import test_all_fingerprints
from .conftest import test_certificates
from .conftest import test_keyring_certificates
from .conftest import test_keys
from .conftest import test_main_fingerprints
def test_is_pgp_fingerprint(
valid_fingerprint: str,
invalid_fingerprint: str,
) -> None:
assert keyring.is_pgp_fingerprint(string=valid_fingerprint) is True
assert keyring.is_pgp_fingerprint(string=invalid_fingerprint) is False
@mark.parametrize(
"create_paths, create_paths_in_keyring_dir",
[
(True, False),
(True, True),
(False, True),
(False, False),
],
)
def test_transform_username_to_keyring_path(
create_paths: bool,
create_paths_in_keyring_dir: bool,
working_dir: Path,
keyring_dir: Path,
) -> None:
paths = [Path("test")]
input_paths = deepcopy(paths)
for index, path in enumerate(paths):
path_in_working_dir = working_dir / path
if create_paths:
path_in_working_dir.mkdir()
if create_paths_in_keyring_dir:
(keyring_dir / path).mkdir(parents=True)
paths[index] = path_in_working_dir
modified_paths = deepcopy(paths)
keyring.transform_username_to_keyring_path(keyring_dir=keyring_dir, paths=paths)
for index, path in enumerate(paths):
if create_paths or (not create_paths and not create_paths_in_keyring_dir):
assert path == modified_paths[index]
if not create_paths and create_paths_in_keyring_dir:
assert path == keyring_dir / input_paths[index]
@mark.parametrize(
"fingerprint_path, create_paths, create_paths_in_keyring_dir",
[
(True, True, False),
(True, True, True),
(True, False, True),
(True, False, False),
(False, True, False),
(False, True, True),
(False, False, True),
(False, False, False),
],
)
def test_transform_fingerprint_to_keyring_path(
fingerprint_path: bool,
create_paths: bool,
create_paths_in_keyring_dir: bool,
working_dir: Path,
keyring_dir: Path,
valid_fingerprint: str,
) -> None:
paths = [Path(valid_fingerprint) if fingerprint_path else Path("test")]
input_paths = deepcopy(paths)
keyring_subdir = keyring_dir / "type" / "username"
for index, path in enumerate(paths):
path_in_working_dir = working_dir / path
if create_paths:
path_in_working_dir.mkdir()
if create_paths_in_keyring_dir:
(keyring_subdir / path).mkdir(parents=True)
paths[index] = path_in_working_dir
modified_paths = deepcopy(paths)
keyring.transform_fingerprint_to_keyring_path(keyring_root=keyring_dir, paths=paths)
for index, path in enumerate(paths):
if create_paths or (not fingerprint_path and not create_paths):
assert path == modified_paths[index]
if not create_paths and fingerprint_path and create_paths_in_keyring_dir:
assert path == keyring_subdir / input_paths[index]
@create_certificate(username=Username("foobar"), uids=[Uid("foobar <foo@bar.xyz>")])
def test_convert(working_dir: Path, keyring_dir: Path) -> None:
keyring.convert(
working_dir=working_dir,
keyring_root=keyring_dir,
sources=test_certificates[Username("foobar")],
target_dir=keyring_dir,
)
with raises(Exception):
keyring.convert(
working_dir=working_dir,
keyring_root=keyring_dir,
sources=test_keys[Username("foobar")],
target_dir=keyring_dir,
)
@create_certificate(username=Username("main"), uids=[Uid("main <foo@bar.xyz>")], keyring_type="main")
@create_certificate(username=Username("other_main"), uids=[Uid("other main <foo@bar.xyz>")], keyring_type="main")
@create_certificate(username=Username("foobar"), uids=[Uid("foobar <foo@bar.xyz>")])
def test_export_ownertrust(working_dir: Path, keyring_dir: Path) -> None:
output = working_dir / "build"
keyring.export_ownertrust(
certs=[keyring_dir / "main"],
keyring_root=keyring_dir,
output=output,
)
with open(file=output, mode="r") as output_file:
for line in output_file.readlines():
assert line.split(":")[0] in test_main_fingerprints
@create_certificate(username=Username("main"), uids=[Uid("main <foo@bar.xyz>")], keyring_type="main")
@create_certificate(username=Username("foobar"), uids=[Uid("foobar <foo@bar.xyz>")])
@create_key_revocation(username=Username("foobar"))
def test_export_revoked(working_dir: Path, keyring_dir: Path) -> None:
output = working_dir / "build"
keyring.export_revoked(
certs=[keyring_dir / "packager"],
keyring_root=keyring_dir,
main_keys=test_main_fingerprints,
output=output,
)
revoked_fingerprints = test_all_fingerprints - test_main_fingerprints
with open(file=output, mode="r") as output_file:
for line in output_file.readlines():
assert line.strip() in revoked_fingerprints
@mark.parametrize("path_exists", [(True), (False)])
@create_certificate(username=Username("main"), uids=[Uid("main <foo@bar.xyz>")], keyring_type="main")
@create_certificate(username=Username("foobar"), uids=[Uid("foobar <foo@bar.xyz>")])
@create_uid_certification(issuer=Username("main"), certified=Username("foobar"), uid=Uid("foobar <foo@bar.xyz>"))
@create_key_revocation(username=Username("foobar"))
def test_get_packets_from_path(working_dir: Path, keyring_dir: Path, path_exists: bool) -> None:
if not path_exists:
assert keyring.get_packets_from_path(path=working_dir / "nope") == []
else:
for username, paths in test_keyring_certificates.items():
for path in paths:
keyring.get_packets_from_path(path=path)
@mark.parametrize("path_exists", [(True), (False)])
@patch("libkeyringctl.keyring.get_packets_from_path")
def test_get_packets_from_listing(get_packets_from_path_mock: Mock, working_dir: Path, path_exists: bool) -> None:
path = working_dir / "path"
if not path_exists:
assert keyring.get_packets_from_listing(path=path) == []
else:
get_packets_from_path_mock.return_value = []
sub_path = path / "sub"
sub_path.mkdir(parents=True)
assert keyring.get_packets_from_listing(path=path) == []
get_packets_from_path_mock.assert_called_once_with(sub_path)
@create_certificate(username=Username("main"), uids=[Uid("main <foo@bar.xyz>")], keyring_type="main")
@create_certificate(username=Username("foobar"), uids=[Uid("foobar <foo@bar.xyz>")])
@create_uid_certification(issuer=Username("main"), certified=Username("foobar"), uid=Uid("foobar <foo@bar.xyz>"))
@create_key_revocation(username=Username("foobar"))
def test_export(working_dir: Path, keyring_dir: Path) -> None:
output_file = working_dir / "output"
empty_dir = working_dir / "empty"
empty_dir.mkdir()
assert not keyring.export(working_dir=working_dir, keyring_root=empty_dir, sources=None, output=output_file)
assert not output_file.exists()
keyring.export(working_dir=working_dir, keyring_root=keyring_dir, sources=None, output=output_file)
assert output_file.exists()
@create_certificate(username=Username("main"), uids=[Uid("main <foo@bar.xyz>")], keyring_type="main")
@create_certificate(username=Username("foobar"), uids=[Uid("foobar <foo@bar.xyz>")])
@create_uid_certification(issuer=Username("main"), certified=Username("foobar"), uid=Uid("foobar <foo@bar.xyz>"))
@create_key_revocation(username=Username("foobar"))
def test_build(working_dir: Path, keyring_dir: Path) -> None:
output_dir = working_dir / "output"
with raises(FileNotFoundError):
empty_dir = working_dir / "empty"
empty_dir.mkdir()
keyring.build(working_dir=working_dir, keyring_root=empty_dir, target_dir=output_dir)
keyring.build(working_dir=working_dir, keyring_root=keyring_dir, target_dir=output_dir)
assert (
(output_dir / "archlinux.gpg").exists()
and (output_dir / "archlinux-trusted").exists()
and (output_dir / "archlinux-revoked").exists()
)
@mark.parametrize(
"create_dir, duplicate_fingerprints, expectation",
[
(True, False, does_not_raise()),
(True, True, raises(Exception)),
(False, False, does_not_raise()),
(False, True, does_not_raise()),
],
)
def test_derive_username_from_fingerprint(
create_dir: bool,
duplicate_fingerprints: bool,
expectation: ContextManager[str],
keyring_dir: Path,
valid_fingerprint: str,
) -> None:
username = "username"
other_username = "other_user"
typed_keyring_dir = keyring_dir / "type"
if create_dir:
(typed_keyring_dir / username / valid_fingerprint).mkdir(parents=True)
if duplicate_fingerprints:
(typed_keyring_dir / other_username / valid_fingerprint).mkdir(parents=True)
with expectation:
returned_username = keyring.derive_username_from_fingerprint(
keyring_dir=typed_keyring_dir,
certificate_fingerprint=Fingerprint(valid_fingerprint),
)
if create_dir and not duplicate_fingerprints:
assert returned_username == username
else:
assert returned_username is None
def test_get_fingerprints_from_paths(keyring_dir: Path, valid_fingerprint: str, valid_subkey_fingerprint: str) -> None:
fingerprint_dir = keyring_dir / "type" / "username" / valid_fingerprint
fingerprint_dir.mkdir(parents=True)
(fingerprint_dir / (fingerprint_dir.name + ".asc")).touch()
fingerprint_subkey_dir = fingerprint_dir / "subkey" / valid_subkey_fingerprint
fingerprint_subkey_dir.mkdir(parents=True)
fingerprint_subkey_asc = fingerprint_subkey_dir / (fingerprint_subkey_dir.name + ".asc")
fingerprint_subkey_asc.touch()
assert keyring.get_fingerprints_from_paths(sources=[fingerprint_subkey_dir]) == set(
[Fingerprint(valid_subkey_fingerprint)]
)
assert keyring.get_fingerprints_from_paths(sources=[fingerprint_dir]) == set([Fingerprint(valid_fingerprint)])