pyproject-rpm-macros/test_pyproject_save_files.py

266 lines
8.5 KiB
Python
Raw Normal View History

import pytest
import yaml
from pathlib import Path
from pprint import pprint
from pyproject_save_files import argparser, generate_file_list, main
from pyproject_save_files import locate_record, parse_record, read_record
from pyproject_save_files import BuildrootPath
DIR = Path(__file__).parent
BINDIR = BuildrootPath("/usr/bin")
DATADIR = BuildrootPath("/usr/share")
SITELIB = BuildrootPath("/usr/lib/python3.7/site-packages")
SITEARCH = BuildrootPath("/usr/lib64/python3.7/site-packages")
yaml_file = DIR / "pyproject_save_files_test_data.yaml"
yaml_data = yaml.safe_load(yaml_file.read_text())
EXPECTED_DICT = yaml_data["classified"]
EXPECTED_FILES = yaml_data["dumped"]
TEST_RECORDS = yaml_data["records"]
def create_root(tmp_path, *records):
r"""
Create mock buildroot in tmp_path
parameters:
tmp_path: path where buildroot should be created
records: dicts with:
path: expected path found in buildroot
content: string content of the file
Example:
>>> record = {'path': '/usr/lib/python/tldr-0.5.dist-info/RECORD', 'content': '__pycache__/tldr.cpython-37.pyc,,\n...'}
>>> create_root(Path('tmp'), record)
PosixPath('tmp/buildroot')
The example creates ./tmp/buildroot/usr/lib/python/tldr-0.5.dist-info/RECORD with the content.
>>> import shutil
>>> shutil.rmtree(Path('./tmp'))
"""
buildroot = tmp_path / "buildroot"
for record in records:
dest = buildroot / Path(record["path"]).relative_to("/")
dest.parent.mkdir(parents=True)
dest.write_text(record["content"])
return buildroot
@pytest.fixture
def tldr_root(tmp_path):
return create_root(tmp_path, TEST_RECORDS["tldr"])
@pytest.fixture
def output(tmp_path):
return tmp_path / "pyproject_files"
def test_locate_record_good(tmp_path):
sitedir = tmp_path / "ha/ha/ha/site-packages"
distinfo = sitedir / "foo-0.6.dist-info"
distinfo.mkdir(parents=True)
record = distinfo / "RECORD"
record.write_text("\n")
sitedir = BuildrootPath.from_real(sitedir, root=tmp_path)
assert locate_record(tmp_path, {sitedir}) == record
def test_locate_record_missing(tmp_path):
sitedir = tmp_path / "ha/ha/ha/site-packages"
distinfo = sitedir / "foo-0.6.dist-info"
distinfo.mkdir(parents=True)
sitedir = BuildrootPath.from_real(sitedir, root=tmp_path)
with pytest.raises(FileNotFoundError):
locate_record(tmp_path, {sitedir})
def test_locate_record_misplaced(tmp_path):
sitedir = tmp_path / "ha/ha/ha/site-packages"
fakedir = tmp_path / "no/no/no/site-packages"
distinfo = fakedir / "foo-0.6.dist-info"
distinfo.mkdir(parents=True)
record = distinfo / "RECORD"
record.write_text("\n")
sitedir = BuildrootPath.from_real(sitedir, root=tmp_path)
with pytest.raises(FileNotFoundError):
locate_record(tmp_path, {sitedir})
def test_locate_record_two_packages(tmp_path):
sitedir = tmp_path / "ha/ha/ha/site-packages"
for name in "foo-0.6.dist-info", "bar-1.8.dist-info":
distinfo = sitedir / name
distinfo.mkdir(parents=True)
record = distinfo / "RECORD"
record.write_text("\n")
sitedir = BuildrootPath.from_real(sitedir, root=tmp_path)
with pytest.raises(FileExistsError):
locate_record(tmp_path, {sitedir})
def test_locate_record_two_sitedirs(tmp_path):
sitedirs = ["ha/ha/ha/site-packages", "ha/ha/ha64/site-packages"]
for idx, sitedir in enumerate(sitedirs):
sitedir = tmp_path / sitedir
distinfo = sitedir / "foo-0.6.dist-info"
distinfo.mkdir(parents=True)
record = distinfo / "RECORD"
record.write_text("\n")
sitedirs[idx] = BuildrootPath.from_real(sitedir, root=tmp_path)
with pytest.raises(FileExistsError):
locate_record(tmp_path, set(sitedirs))
def test_parse_record_tldr():
record_path = BuildrootPath(TEST_RECORDS["tldr"]["path"])
record_content = read_record(DIR / "test_RECORD")
output = list(parse_record(record_path, record_content))
pprint(output)
expected = [
BINDIR / "__pycache__/tldr.cpython-37.pyc",
BINDIR / "tldr",
BINDIR / "tldr.py",
SITELIB / "__pycache__/tldr.cpython-37.pyc",
SITELIB / "tldr-0.5.dist-info/INSTALLER",
SITELIB / "tldr-0.5.dist-info/LICENSE",
SITELIB / "tldr-0.5.dist-info/METADATA",
SITELIB / "tldr-0.5.dist-info/RECORD",
SITELIB / "tldr-0.5.dist-info/WHEEL",
SITELIB / "tldr-0.5.dist-info/top_level.txt",
SITELIB / "tldr.py",
]
assert output == expected
def test_parse_record_tensorflow():
long = "tensorflow_core/include/tensorflow/core/common_runtime/base_collective_executor.h"
record_path = SITEARCH / "tensorflow-2.1.0.dist-info/RECORD"
record_content = [
["../../../bin/toco_from_protos", "sha256=hello", "289"],
[f"../../../lib/python3.7/site-packages/{long}", "sha256=darkness", "1024"],
["tensorflow-2.1.0.dist-info/METADATA", "sha256=friend", "2859"],
]
output = list(parse_record(record_path, record_content))
pprint(output)
expected = [
BINDIR / "toco_from_protos",
SITELIB / long,
SITEARCH / "tensorflow-2.1.0.dist-info/METADATA",
]
assert output == expected
def remove_others(expected):
return [p for p in expected if not (p.startswith(str(BINDIR)) or p.startswith(str(DATADIR)) or p.endswith(".pth"))]
@pytest.mark.parametrize("include_auto", (True, False))
@pytest.mark.parametrize("package, glob, expected", EXPECTED_FILES)
def test_generate_file_list(package, glob, expected, include_auto):
paths_dict = EXPECTED_DICT[package]
modules_glob = {glob}
if not include_auto:
expected = remove_others(expected)
tested = generate_file_list(paths_dict, modules_glob, include_auto)
assert tested == expected
def test_generate_file_list_unused_glob():
paths_dict = EXPECTED_DICT["kerberos"]
modules_glob = {"kerberos", "unused_glob1", "unused_glob2", "kerb*"}
with pytest.raises(ValueError) as excinfo:
generate_file_list(paths_dict, modules_glob, True)
assert "unused_glob1, unused_glob2" in str(excinfo.value)
assert "kerb" not in str(excinfo.value)
def default_options(output, mock_root):
return [
"--output",
str(output),
"--buildroot",
str(mock_root),
"--sitelib",
str(SITELIB),
"--sitearch",
str(SITEARCH),
"--python-version",
"3.7", # test data are for 3.7
]
@pytest.mark.parametrize("include_auto", (True, False))
@pytest.mark.parametrize("package, glob, expected", EXPECTED_FILES)
def test_cli(tmp_path, package, glob, expected, include_auto):
mock_root = create_root(tmp_path, TEST_RECORDS[package])
output = tmp_path / "files"
globs = [glob, "+auto"] if include_auto else [glob]
cli_args = argparser().parse_args([*default_options(output, mock_root), *globs])
main(cli_args)
if not include_auto:
expected = remove_others(expected)
tested = output.read_text()
assert tested == "\n".join(expected) + "\n"
def test_cli_no_RECORD(tmp_path):
mock_root = create_root(tmp_path)
output = tmp_path / "files"
cli_args = argparser().parse_args([*default_options(output, mock_root), "tldr*"])
with pytest.raises(FileNotFoundError):
main(cli_args)
def test_cli_misplaced_RECORD(tmp_path, output):
record = {"path": "/usr/lib/", "content": TEST_RECORDS["tldr"]["content"]}
mock_root = create_root(tmp_path, record)
cli_args = argparser().parse_args([*default_options(output, mock_root), "tldr*"])
with pytest.raises(FileNotFoundError):
main(cli_args)
def test_cli_find_too_many_RECORDS(tldr_root, output):
mock_root = create_root(tldr_root.parent, TEST_RECORDS["tensorflow"])
cli_args = argparser().parse_args([*default_options(output, mock_root), "tldr*"])
with pytest.raises(FileExistsError):
main(cli_args)
def test_cli_bad_argument(tldr_root, output):
cli_args = argparser().parse_args(
[*default_options(output, tldr_root), "tldr*", "+foodir"]
)
with pytest.raises(ValueError):
main(cli_args)
def test_cli_bad_option(tldr_root, output):
cli_args = argparser().parse_args(
[*default_options(output, tldr_root), "tldr*", "you_cannot_have_this"]
)
with pytest.raises(ValueError):
main(cli_args)
def test_cli_bad_namespace(tldr_root, output):
cli_args = argparser().parse_args(
[*default_options(output, tldr_root), "tldr.didntread"]
)
with pytest.raises(ValueError):
main(cli_args)