Blame test_pyproject_save_files.py

2800b49
import pytest
2800b49
import yaml
2800b49
2800b49
from pathlib import Path
2800b49
from pprint import pprint
2800b49
7cc5634
from pyproject_preprocess_record import parse_record, read_record, save_parsed_record
2800b49
7cc5634
from pyproject_save_files import argparser, generate_file_list, BuildrootPath
7cc5634
from pyproject_save_files import main as save_files_main
c1baa53
from pyproject_save_files import module_names_from_path
2800b49
2800b49
DIR = Path(__file__).parent
c3a20e9
PREFIX = Path("/usr")
2800b49
BINDIR = BuildrootPath("/usr/bin")
c124941
DATADIR = BuildrootPath("/usr/share")
2800b49
SITELIB = BuildrootPath("/usr/lib/python3.7/site-packages")
2800b49
SITEARCH = BuildrootPath("/usr/lib64/python3.7/site-packages")
2800b49
2800b49
yaml_file = DIR / "pyproject_save_files_test_data.yaml"
2800b49
yaml_data = yaml.safe_load(yaml_file.read_text())
2800b49
EXPECTED_DICT = yaml_data["classified"]
2800b49
EXPECTED_FILES = yaml_data["dumped"]
2800b49
TEST_RECORDS = yaml_data["records"]
5169e0e
TEST_METADATAS = yaml_data["metadata"]
2800b49
2800b49
7cc5634
@pytest.fixture
7cc5634
def tldr_root(tmp_path):
7cc5634
    prepare_pyproject_record(tmp_path, package="tldr")
7cc5634
    return tmp_path
2800b49
2800b49
7cc5634
@pytest.fixture
7cc5634
def pyproject_record(tmp_path):
7cc5634
    return tmp_path / "pyproject-record"
2800b49
2800b49
7cc5634
def prepare_pyproject_record(tmp_path, package=None, content=None):
2800b49
    """
7cc5634
    Creates RECORD from test data and then uses
7cc5634
    functions from pyproject_process_record to convert
7cc5634
    it to pyproject-record file which is then
7cc5634
    further processed by functions from pyproject_save_files.
7cc5634
    """
7cc5634
    record_file = tmp_path / "RECORD"
7cc5634
    pyproject_record = tmp_path / "pyproject-record"
2800b49
7cc5634
    if package is not None:
7cc5634
        # Get test data and write dist-info/RECORD file
7cc5634
        record_path = BuildrootPath(TEST_RECORDS[package]["path"])
7cc5634
        record_file.write_text(TEST_RECORDS[package]["content"])
5169e0e
        if package in TEST_METADATAS:
5169e0e
            metadata_path = BuildrootPath(TEST_METADATAS[package]["path"]).to_real(tmp_path)
5169e0e
            metadata_path.parent.mkdir(parents=True, exist_ok=True)
5169e0e
            metadata_path.write_text(TEST_METADATAS[package]["content"])
7cc5634
        # Parse RECORD file
7cc5634
        parsed_record = parse_record(record_path, read_record(record_file))
7cc5634
        # Save JSON content to pyproject-record
7cc5634
        save_parsed_record(record_path, parsed_record, pyproject_record)
7cc5634
    elif content is not None:
7cc5634
        save_parsed_record(*content, output_file=pyproject_record)
2800b49
2800b49
2800b49
@pytest.fixture
c1baa53
def output_files(tmp_path):
2800b49
    return tmp_path / "pyproject_files"
2800b49
c1baa53
@pytest.fixture
c1baa53
def output_modules(tmp_path):
c1baa53
    return tmp_path / "pyproject_modules"
c1baa53
2800b49
2800b49
def test_parse_record_tldr():
2800b49
    record_path = BuildrootPath(TEST_RECORDS["tldr"]["path"])
2800b49
    record_content = read_record(DIR / "test_RECORD")
2800b49
    output = list(parse_record(record_path, record_content))
2800b49
    pprint(output)
2800b49
    expected = [
228f394
        str(BINDIR / "__pycache__/tldr.cpython-37.pyc"),
228f394
        str(BINDIR / "tldr"),
228f394
        str(BINDIR / "tldr.py"),
228f394
        str(SITELIB / "__pycache__/tldr.cpython-37.pyc"),
228f394
        str(SITELIB / "tldr-0.5.dist-info/INSTALLER"),
228f394
        str(SITELIB / "tldr-0.5.dist-info/LICENSE"),
228f394
        str(SITELIB / "tldr-0.5.dist-info/METADATA"),
228f394
        str(SITELIB / "tldr-0.5.dist-info/RECORD"),
228f394
        str(SITELIB / "tldr-0.5.dist-info/WHEEL"),
228f394
        str(SITELIB / "tldr-0.5.dist-info/top_level.txt"),
228f394
        str(SITELIB / "tldr.py"),
2800b49
    ]
2800b49
    assert output == expected
2800b49
2800b49
2800b49
def test_parse_record_tensorflow():
2800b49
    long = "tensorflow_core/include/tensorflow/core/common_runtime/base_collective_executor.h"
2800b49
    record_path = SITEARCH / "tensorflow-2.1.0.dist-info/RECORD"
2800b49
    record_content = [
2800b49
        ["../../../bin/toco_from_protos", "sha256=hello", "289"],
2800b49
        [f"../../../lib/python3.7/site-packages/{long}", "sha256=darkness", "1024"],
2800b49
        ["tensorflow-2.1.0.dist-info/METADATA", "sha256=friend", "2859"],
2800b49
    ]
2800b49
    output = list(parse_record(record_path, record_content))
2800b49
    pprint(output)
2800b49
    expected = [
228f394
        str(BINDIR / "toco_from_protos"),
228f394
        str(SITELIB / long),
228f394
        str(SITEARCH / "tensorflow-2.1.0.dist-info/METADATA"),
2800b49
    ]
2800b49
    assert output == expected
2800b49
2800b49
e2c64e7
def remove_others(expected):
c3a20e9
    return [
c3a20e9
        p for p in expected
c3a20e9
        if not (
c3a20e9
            p.startswith(str(BINDIR)) or
c3a20e9
            p.endswith(".pth") or
c3a20e9
            p.endswith("*") or
c3a20e9
            p.rpartition(' ')[-1].startswith(str(DATADIR))
c3a20e9
        )
c3a20e9
    ]
2800b49
2800b49
e2c64e7
@pytest.mark.parametrize("include_auto", (True, False))
c1baa53
@pytest.mark.parametrize("package, glob, expected_files, expected_modules", EXPECTED_FILES)
c1baa53
def test_generate_file_list(package, glob, expected_files, include_auto, expected_modules):
2800b49
    paths_dict = EXPECTED_DICT[package]
2800b49
    modules_glob = {glob}
e2c64e7
    if not include_auto:
c1baa53
        expected_files = remove_others(expected_files)
e2c64e7
    tested = generate_file_list(paths_dict, modules_glob, include_auto)
2800b49
c1baa53
    assert tested == expected_files
2800b49
2800b49
2800b49
def test_generate_file_list_unused_glob():
2800b49
    paths_dict = EXPECTED_DICT["kerberos"]
2800b49
    modules_glob = {"kerberos", "unused_glob1", "unused_glob2", "kerb*"}
2800b49
    with pytest.raises(ValueError) as excinfo:
2800b49
        generate_file_list(paths_dict, modules_glob, True)
2800b49
2800b49
    assert "unused_glob1, unused_glob2" in str(excinfo.value)
2800b49
    assert "kerb" not in str(excinfo.value)
2800b49
2800b49
c1baa53
@pytest.mark.parametrize(
c1baa53
    "path, expected",
c1baa53
    [
c1baa53
        ("foo/bar/baz.py", {"foo", "foo.bar", "foo.bar.baz"}),
c1baa53
        ("foo/bar.py", {"foo", "foo.bar"}),
c1baa53
        ("foo.py", {"foo"}),
c1baa53
        ("foo/bar.so.2", set()),
c1baa53
        ("foo.cpython-37m-x86_64-linux-gnu.so", {"foo"}),
c1baa53
        ("foo/_api/v2/__init__.py", set()),
c1baa53
        ("foo/__init__.py", {"foo"}),
c1baa53
        ("foo/_priv.py", set()),
c1baa53
        ("foo/_bar/lib.so", set()),
c1baa53
        ("foo/bar/baz.so", {"foo", "foo.bar", "foo.bar.baz"}),
c1baa53
        ("foo/bar/baz.pth", set()),
c1baa53
        ("foo/bar/baz.pyc", set()),
c1baa53
        ("def.py", set()),
c1baa53
        ("foo-bar/baz.py", set()),
c1baa53
        ("foobar/12baz.py", set()),
c1baa53
        ("foo/\nbar/baz.py", set()),
c1baa53
        ("foo/+bar/baz.py", set()),
c1baa53
        ("foo/__init__.cpython-39-x86_64-linux-gnu.so", {"foo"}),
c1baa53
        ("foo/bar/__pycache__/abc.cpython-37.pyc", set()),
c1baa53
    ],
c1baa53
)
c1baa53
def test_module_names_from_path(path, expected):
c1baa53
    tested = Path(path)
c1baa53
    assert module_names_from_path(tested) == expected
c1baa53
c1baa53
c1baa53
def default_options(output_files, output_modules, mock_root, pyproject_record):
2800b49
    return [
c1baa53
        "--output-files",
c1baa53
        str(output_files),
c1baa53
        "--output-modules",
c1baa53
        str(output_modules),
2800b49
        "--buildroot",
2800b49
        str(mock_root),
2800b49
        "--sitelib",
2800b49
        str(SITELIB),
2800b49
        "--sitearch",
2800b49
        str(SITEARCH),
2800b49
        "--python-version",
7cc5634
        "3.7",  # test data are for 3.7,
7cc5634
        "--pyproject-record",
c3a20e9
        str(pyproject_record),
c3a20e9
        "--prefix",
c3a20e9
        str(PREFIX),
2800b49
    ]
2800b49
2800b49
e2c64e7
@pytest.mark.parametrize("include_auto", (True, False))
c1baa53
@pytest.mark.parametrize("package, glob, expected_files, expected_modules", EXPECTED_FILES)
c1baa53
def test_cli(tmp_path, package, glob, expected_files, expected_modules, include_auto, pyproject_record):
7cc5634
    prepare_pyproject_record(tmp_path, package)
c1baa53
    output_files = tmp_path / "files"
c1baa53
    output_modules = tmp_path / "modules"
e2c64e7
    globs = [glob, "+auto"] if include_auto else [glob]
c1baa53
    cli_args = argparser().parse_args([*default_options(output_files, output_modules, tmp_path, pyproject_record), *globs])
7cc5634
    save_files_main(cli_args)
2800b49
e2c64e7
    if not include_auto:
c1baa53
        expected_files = remove_others(expected_files)
c1baa53
    tested_files = output_files.read_text()
c1baa53
    assert tested_files == "\n".join(expected_files) + "\n"
c1baa53
c1baa53
    tested_modules = output_modules.read_text().split()
c1baa53
c1baa53
    assert tested_modules == expected_modules
2800b49
2800b49
7cc5634
def test_cli_no_pyproject_record(tmp_path, pyproject_record):
c1baa53
    output_files = tmp_path / "files"
c1baa53
    output_modules = tmp_path / "modules"
c1baa53
    cli_args = argparser().parse_args([*default_options(output_files, output_modules, tmp_path, pyproject_record), "tldr*"])
2800b49
2800b49
    with pytest.raises(FileNotFoundError):
7cc5634
        save_files_main(cli_args)
2800b49
2800b49
c1baa53
def test_cli_too_many_RECORDS(tldr_root, output_files, output_modules, pyproject_record):
7cc5634
    # Two calls to simulate how %pyproject_install process more than one RECORD file
7cc5634
    prepare_pyproject_record(tldr_root,
7cc5634
                             content=("foo/bar/dist-info/RECORD", []))
7cc5634
    prepare_pyproject_record(tldr_root,
7cc5634
                             content=("foo/baz/dist-info/RECORD", []))
c1baa53
    cli_args = argparser().parse_args([*default_options(output_files, output_modules, tldr_root, pyproject_record), "tldr*"])
2800b49
2800b49
    with pytest.raises(FileExistsError):
7cc5634
        save_files_main(cli_args)
2800b49
2800b49
c1baa53
def test_cli_bad_argument(tldr_root, output_files, output_modules, pyproject_record):
2800b49
    cli_args = argparser().parse_args(
c1baa53
        [*default_options(output_files, output_modules, tldr_root, pyproject_record), "tldr*", "+foodir"]
2800b49
    )
2800b49
2800b49
    with pytest.raises(ValueError):
7cc5634
        save_files_main(cli_args)
2800b49
2800b49
c1baa53
def test_cli_bad_option(tldr_root, output_files, output_modules, pyproject_record):
7cc5634
    prepare_pyproject_record(tldr_root.parent, content=("RECORD1", []))
2800b49
    cli_args = argparser().parse_args(
c1baa53
        [*default_options(output_files, output_modules, tldr_root, pyproject_record), "tldr*", "you_cannot_have_this"]
2800b49
    )
2800b49
2800b49
    with pytest.raises(ValueError):
7cc5634
        save_files_main(cli_args)
2800b49
2800b49
c1baa53
def test_cli_bad_namespace(tldr_root, output_files, output_modules, pyproject_record):
2800b49
    cli_args = argparser().parse_args(
c1baa53
        [*default_options(output_files, output_modules, tldr_root, pyproject_record), "tldr.didntread"]
2800b49
    )
2800b49
2800b49
    with pytest.raises(ValueError):
7cc5634
        save_files_main(cli_args)