git mirror - github.com/owenewans/holy - branch master
clone: https://src.holypkg.eu/holy/

file tests/rpm-import.py

#!/usr/bin/env python3
import os
import io
import hashlib
import shutil
import subprocess
import sys
import tarfile
import tempfile
from pathlib import Path


def build(root, fmt, script=""):
    spec = root / "SPECS" / "holy-rpm-fixture.spec"
    spec.write_text("""Name: holy-rpm-fixture
Version: 1.0
Release: 1
Summary: Holy RPM import fixture
License: MIT
BuildArch: noarch
Requires: sample-lib >= 1.2
%description
Local RPM import fixture.
%install
mkdir -p %{buildroot}/etc %{buildroot}/usr/share/holy-rpm-fixture
printf 'config\\n' > %{buildroot}/etc/holy-rpm-fixture.conf
printf 'payload\\n' > %{buildroot}/usr/share/holy-rpm-fixture/data
ln %{buildroot}/usr/share/holy-rpm-fixture/data %{buildroot}/usr/share/holy-rpm-fixture/data-hardlink
ln -s data %{buildroot}/usr/share/holy-rpm-fixture/data-symlink
touch %{buildroot}/usr/share/holy-rpm-fixture/empty
""" + script + """
%files
%config(noreplace) /etc/holy-rpm-fixture.conf
/usr/share/holy-rpm-fixture/data
/usr/share/holy-rpm-fixture/data-hardlink
/usr/share/holy-rpm-fixture/data-symlink
/usr/share/holy-rpm-fixture/empty
""")
    subprocess.run(["rpmbuild", "-bb", "--define", f"_rpmformat {fmt}",
                    "--define", f"_topdir {root}", str(spec)],
                   check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    return root / "RPMS" / "noarch" / "holy-rpm-fixture-1.0-1.noarch.rpm"


def build_provider(root, version, epoch=0):
    spec = root / "SPECS" / "holy-rpm-provider.spec"
    spec.write_text(f"""Name: holy-rpm-provider
Version: {version}
Release: 1
Epoch: {epoch}
Summary: Holy RPM provider fixture
License: MIT
BuildArch: noarch
Provides: sample-lib = {str(epoch) + ':' if epoch else ''}{version}-1
%description
Local RPM provider fixture.
%install
mkdir -p %{{buildroot}}/usr/share/holy-rpm-provider
printf 'provider\\n' > %{{buildroot}}/usr/share/holy-rpm-provider/data
%files
/usr/share/holy-rpm-provider/data
""")
    subprocess.run(["rpmbuild", "-bb", "--define", "_rpmformat 4",
                    "--define", f"_topdir {root}", str(spec)],
                   check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    return root / "RPMS" / "noarch" / f"holy-rpm-provider-{version}-1.noarch.rpm"


def run(binary, package, output):
    return subprocess.run([binary, "import", str(package), "--source", "rpm-fixture",
                           "--format", "rpm", "--output", str(output)],
                          text=True, capture_output=True)


def main():
    for tool in ("rpmbuild", "lz4"):
        if not shutil.which(tool):
            print(f"{tool} required for RPM import fixture", file=sys.stderr)
            return 6
    binary = os.path.abspath(sys.argv[1])
    with tempfile.TemporaryDirectory() as temp:
        root = Path(temp)
        (root / "SPECS").mkdir()
        package = build(root, 4)
        good = root / "good"
        result = run(binary, package, good)
        assert result.returncode == 0, result.stderr
        artifact = good / "holy-rpm-fixture--noarch--nolibc.holy"
        assert artifact.is_file() and (good / "conversion").is_file()
        contents = subprocess.run(["lz4", "-dc", str(artifact)], check=True,
                                  capture_output=True).stdout
        with tarfile.open(fileobj=io.BytesIO(contents)) as archive:
            def read(name):
                return archive.extractfile(name).read().decode()
            assert 'x-version-family rpm' in read('HOLY/meta')
            assert 'file "etc/holy-rpm-fixture.conf"' in read('HOLY/files')
            assert ' config ' in read('HOLY/files')
            assert 'data-hardlink' in read('HOLY/files')
            assert 'data-symlink' in read('HOLY/files')
            assert '"package" "sample-lib" "any" "any" "ge" "1.2"' in read('HOLY/deps')
            assert 'rpmlib(' not in read('HOLY/deps')
            assert 'rpmlib(' in read('HOLY/origin')
            assert 'verification unverified' in read('HOLY/origin')
        providers = []
        for version in ("1.1", "1.3"):
            provider_rpm = build_provider(root, version)
            target = root / f"provider-{version}"
            result = run(binary, provider_rpm, target)
            assert result.returncode == 0, result.stderr
            providers.append(target / "holy-rpm-provider--noarch--nolibc.holy")
        solve = lambda *items: subprocess.run([binary, "solve", *["local:" + str(item)
                                  for item in items]], text=True, capture_output=True)
        assert solve(artifact, providers[0]).returncode == 4
        result = solve(artifact, *providers)
        assert result.returncode == 0, result.stderr
        assert 'selected ' + hashlib.sha256(providers[1].read_bytes()).hexdigest() in result.stdout
        epoch_rpm = build_provider(root, "0.1", epoch=1)
        epoch_output = root / "provider-epoch"
        result = run(binary, epoch_rpm, epoch_output)
        assert result.returncode == 0, result.stderr
        epoch_package = epoch_output / "holy-rpm-provider--noarch--nolibc.holy"
        assert solve(artifact, epoch_package).returncode == 0
        truncated = root / "truncated.rpm"
        truncated.write_bytes(package.read_bytes()[:-16])
        assert run(binary, truncated, root / "truncated").returncode != 0
        package = build(root, 4, "%post\nprintf 'script\\n'\n")
        result = run(binary, package, root / "script")
        assert result.returncode == 3, result.stderr
        package = build(root, 6)
        result = run(binary, package, root / "v6")
        assert result.returncode == 0, result.stderr
        assert (root / "v6" / "holy-rpm-fixture--noarch--nolibc.holy").is_file()
        truncated.write_bytes(package.read_bytes()[:-16])
        assert run(binary, truncated, root / "truncated-v6").returncode != 0
    return 0


if __name__ == "__main__":
    sys.exit(main())