mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-24 15:27:17 +00:00
Previously if package is VCS and version in PKGBUILD doesn't match to AUR one, then makepkg will update pkgbuild ignoring all previous pkgrel patches With this change during task init dry ryn process is always run for vcs packages
515 lines
20 KiB
Python
515 lines
20 KiB
Python
import copy
|
|
|
|
from pathlib import Path
|
|
from pytest_mock import MockerFixture
|
|
from unittest.mock import MagicMock, call as MockCall
|
|
|
|
from ahriman.core.alpm.pacman import Pacman
|
|
from ahriman.core.configuration import Configuration
|
|
from ahriman.core.utils import utcnow
|
|
from ahriman.models.aur_package import AURPackage
|
|
from ahriman.models.package import Package
|
|
from ahriman.models.package_description import PackageDescription
|
|
from ahriman.models.pkgbuild import Pkgbuild
|
|
from ahriman.models.pkgbuild_patch import PkgbuildPatch
|
|
|
|
|
|
def test_depends(package_python_schedule: Package) -> None:
|
|
"""
|
|
must return combined list of dependencies
|
|
"""
|
|
assert all(
|
|
set(package_python_schedule.depends).intersection(package.depends)
|
|
for package in package_python_schedule.packages.values()
|
|
)
|
|
|
|
|
|
def test_depends_build(package_ahriman: Package, package_python_schedule: Package) -> None:
|
|
"""
|
|
must return full list of packages required for build
|
|
"""
|
|
assert all(
|
|
set(package_ahriman.depends_build).intersection(package.depends)
|
|
for package in package_ahriman.packages.values()
|
|
)
|
|
assert all(
|
|
set(package_ahriman.depends_build).intersection(package.make_depends)
|
|
for package in package_ahriman.packages.values()
|
|
)
|
|
assert all(
|
|
set(package_ahriman.depends_build).intersection(package.check_depends)
|
|
for package in package_ahriman.packages.values()
|
|
)
|
|
|
|
assert all(
|
|
set(package_python_schedule.depends_build).intersection(package.depends)
|
|
for package in package_python_schedule.packages.values()
|
|
)
|
|
# there is no make dependencies for python-schedule
|
|
|
|
|
|
def test_depends_build_with_version_and_overlap(mocker: MockerFixture, resource_path_root: Path) -> None:
|
|
"""
|
|
must load correct list of dependencies with version
|
|
"""
|
|
pkgbuild = resource_path_root / "models" / "package_gcc10_pkgbuild"
|
|
mocker.patch("ahriman.models.pkgbuild.Pkgbuild.from_file", return_value=Pkgbuild.from_file(pkgbuild))
|
|
|
|
package_gcc10 = Package.from_build(Path("local"), "x86_64", None)
|
|
assert package_gcc10.depends_build == {
|
|
"glibc", "zstd", # depends
|
|
"doxygen", "binutils", "git", "libmpc", "python", # make depends
|
|
"dejagnu", "inetutils", # check depends
|
|
}
|
|
|
|
|
|
def test_depends_check(package_ahriman: Package) -> None:
|
|
"""
|
|
must return list of test dependencies
|
|
"""
|
|
assert all(
|
|
set(package_ahriman.depends_check).intersection(package.check_depends)
|
|
for package in package_ahriman.packages.values()
|
|
)
|
|
|
|
|
|
def test_depends_make(package_ahriman: Package) -> None:
|
|
"""
|
|
must return list of make dependencies
|
|
"""
|
|
assert all(
|
|
set(package_ahriman.depends_make).intersection(package.make_depends)
|
|
for package in package_ahriman.packages.values()
|
|
)
|
|
|
|
|
|
def test_depends_opt(package_ahriman: Package) -> None:
|
|
"""
|
|
must return list of optional dependencies
|
|
"""
|
|
assert all(
|
|
set(package_ahriman.depends_opt).intersection(package.opt_depends)
|
|
for package in package_ahriman.packages.values()
|
|
)
|
|
|
|
|
|
def test_groups(package_ahriman: Package) -> None:
|
|
"""
|
|
must return list of groups for each package
|
|
"""
|
|
assert all(
|
|
all(group in package_ahriman.groups for group in package.groups)
|
|
for package in package_ahriman.packages.values()
|
|
)
|
|
assert sorted(package_ahriman.groups) == package_ahriman.groups
|
|
|
|
|
|
def test_is_single_package_false(package_python_schedule: Package) -> None:
|
|
"""
|
|
python-schedule must not be single package
|
|
"""
|
|
assert not package_python_schedule.is_single_package
|
|
|
|
|
|
def test_is_single_package_true(package_ahriman: Package) -> None:
|
|
"""
|
|
ahriman must be single package
|
|
"""
|
|
assert package_ahriman.is_single_package
|
|
|
|
|
|
def test_is_vcs_false(package_ahriman: Package) -> None:
|
|
"""
|
|
ahriman must not be VCS package
|
|
"""
|
|
assert not package_ahriman.is_vcs
|
|
|
|
|
|
def test_is_vcs_true(package_tpacpi_bat_git: Package) -> None:
|
|
"""
|
|
tpacpi-bat-git must be VCS package
|
|
"""
|
|
assert package_tpacpi_bat_git.is_vcs
|
|
|
|
|
|
def test_licenses(package_ahriman: Package) -> None:
|
|
"""
|
|
must return list of licenses for each package
|
|
"""
|
|
assert all(
|
|
all(lic in package_ahriman.licenses for lic in package.licenses)
|
|
for package in package_ahriman.packages.values()
|
|
)
|
|
assert sorted(package_ahriman.licenses) == package_ahriman.licenses
|
|
|
|
|
|
def test_packages_full(package_ahriman: Package) -> None:
|
|
"""
|
|
must return full list of packages including provides
|
|
"""
|
|
package_ahriman.packages[package_ahriman.base].provides = [f"{package_ahriman.base}-git"]
|
|
assert package_ahriman.packages_full == [package_ahriman.base, f"{package_ahriman.base}-git"]
|
|
|
|
|
|
def test_from_archive(package_ahriman: Package, pyalpm_handle: MagicMock, mocker: MockerFixture) -> None:
|
|
"""
|
|
must construct package from alpm library
|
|
"""
|
|
mocker.patch("ahriman.models.package_description.PackageDescription.from_package",
|
|
return_value=package_ahriman.packages[package_ahriman.base])
|
|
generated = Package.from_archive(Path("path"), pyalpm_handle)
|
|
generated.remote = package_ahriman.remote
|
|
|
|
assert generated == package_ahriman
|
|
|
|
|
|
def test_from_aur(package_ahriman: Package, aur_package_ahriman: AURPackage, mocker: MockerFixture) -> None:
|
|
"""
|
|
must construct package from aur
|
|
"""
|
|
mocker.patch("ahriman.core.alpm.remote.AUR.info", return_value=aur_package_ahriman)
|
|
|
|
package = Package.from_aur(package_ahriman.base, package_ahriman.packager)
|
|
assert package_ahriman.base == package.base
|
|
assert package_ahriman.version == package.version
|
|
assert package_ahriman.packages.keys() == package.packages.keys()
|
|
assert package_ahriman.packager == package.packager
|
|
|
|
|
|
def test_from_build(package_ahriman: Package, mocker: MockerFixture, resource_path_root: Path) -> None:
|
|
"""
|
|
must construct package from PKGBUILD
|
|
"""
|
|
pkgbuild = resource_path_root / "models" / "package_ahriman_pkgbuild"
|
|
mocker.patch("ahriman.models.pkgbuild.Pkgbuild.from_file", return_value=Pkgbuild.from_file(pkgbuild))
|
|
|
|
package = Package.from_build(Path("path"), "x86_64", "packager")
|
|
assert package_ahriman.packages.keys() == package.packages.keys()
|
|
package_ahriman.packages = package.packages # we are not going to test PackageDescription here
|
|
package_ahriman.remote = package.remote
|
|
assert package_ahriman == package
|
|
|
|
|
|
def test_from_build_multiple_packages(mocker: MockerFixture, resource_path_root: Path) -> None:
|
|
"""
|
|
must construct package from PKGBUILD with dependencies per-package overrides
|
|
"""
|
|
pkgbuild = resource_path_root / "models" / "package_gcc10_pkgbuild"
|
|
mocker.patch("ahriman.models.pkgbuild.Pkgbuild.from_file", return_value=Pkgbuild.from_file(pkgbuild))
|
|
|
|
package = Package.from_build(Path("path"), "x86_64", None)
|
|
assert package.packages == {
|
|
"gcc10": PackageDescription(
|
|
depends=["gcc10-libs=10.5.0-2", "binutils>=2.28", "libmpc", "zstd"],
|
|
make_depends=["binutils", "doxygen", "git", "libmpc", "python"],
|
|
opt_depends=[],
|
|
check_depends=["dejagnu", "inetutils"],
|
|
),
|
|
"gcc10-libs": PackageDescription(
|
|
depends=["glibc>=2.27"],
|
|
make_depends=["binutils", "doxygen", "git", "libmpc", "python"],
|
|
opt_depends=[],
|
|
check_depends=["dejagnu", "inetutils"],
|
|
),
|
|
"gcc10-fortran": PackageDescription(
|
|
depends=["gcc10=10.5.0-2"],
|
|
make_depends=["binutils", "doxygen", "git", "libmpc", "python"],
|
|
opt_depends=[],
|
|
check_depends=["dejagnu", "inetutils"],
|
|
),
|
|
}
|
|
|
|
|
|
def test_from_build_architecture(mocker: MockerFixture, resource_path_root: Path) -> None:
|
|
"""
|
|
must construct package with architecture specific depends list
|
|
"""
|
|
pkgbuild = resource_path_root / "models" / "package_jellyfin-ffmpeg6-bin_pkgbuild"
|
|
mocker.patch("ahriman.models.pkgbuild.Pkgbuild.from_file", return_value=Pkgbuild.from_file(pkgbuild))
|
|
|
|
package = Package.from_build(Path("path"), "x86_64", None)
|
|
assert package.packages == {
|
|
"jellyfin-ffmpeg6-bin": PackageDescription(
|
|
depends=["glibc"],
|
|
make_depends=[],
|
|
opt_depends=[
|
|
"intel-media-driver: for Intel VAAPI support (Broadwell and newer)",
|
|
"intel-media-sdk: for Intel Quick Sync Video",
|
|
"onevpl-intel-gpu: for Intel Quick Sync Video (12th Gen and newer)",
|
|
"intel-compute-runtime: for Intel OpenCL runtime based Tonemapping",
|
|
"libva-intel-driver: for Intel legacy VAAPI support (10th Gen and older)",
|
|
"libva-mesa-driver: for AMD VAAPI support",
|
|
"nvidia-utils: for Nvidia NVDEC/NVENC support",
|
|
"opencl-amd: for AMD OpenCL runtime based Tonemapping",
|
|
"vulkan-radeon: for AMD RADV Vulkan support",
|
|
"vulkan-intel: for Intel ANV Vulkan support",
|
|
],
|
|
),
|
|
}
|
|
|
|
|
|
def test_from_json_view_1(package_ahriman: Package) -> None:
|
|
"""
|
|
must construct same object from json
|
|
"""
|
|
assert Package.from_json(package_ahriman.view()) == package_ahriman
|
|
|
|
|
|
def test_from_json_view_2(package_python_schedule: Package) -> None:
|
|
"""
|
|
must construct same object from json (double package)
|
|
"""
|
|
assert Package.from_json(package_python_schedule.view()) == package_python_schedule
|
|
|
|
|
|
def test_from_json_view_3(package_tpacpi_bat_git: Package) -> None:
|
|
"""
|
|
must construct same object from json (git package)
|
|
"""
|
|
assert Package.from_json(package_tpacpi_bat_git.view()) == package_tpacpi_bat_git
|
|
|
|
|
|
def test_from_official(package_ahriman: Package, aur_package_ahriman: AURPackage, pacman: Pacman,
|
|
mocker: MockerFixture) -> None:
|
|
"""
|
|
must construct package from official repository
|
|
"""
|
|
mocker.patch("ahriman.core.alpm.remote.Official.info", return_value=aur_package_ahriman)
|
|
|
|
package = Package.from_official(package_ahriman.base, pacman, package_ahriman.packager)
|
|
assert package_ahriman.base == package.base
|
|
assert package_ahriman.version == package.version
|
|
assert package_ahriman.packages.keys() == package.packages.keys()
|
|
assert package_ahriman.packager == package.packager
|
|
|
|
|
|
def test_local_files(mocker: MockerFixture, resource_path_root: Path) -> None:
|
|
"""
|
|
must extract local file sources
|
|
"""
|
|
pkgbuild = resource_path_root / "models" / "package_yay_pkgbuild"
|
|
parsed_pkgbuild = Pkgbuild.from_file(pkgbuild)
|
|
parsed_pkgbuild.fields["source"] = PkgbuildPatch("source", ["local-file.tar.gz"])
|
|
mocker.patch("ahriman.models.pkgbuild.Pkgbuild.from_file", return_value=parsed_pkgbuild)
|
|
mocker.patch("ahriman.models.package.Package.supported_architectures", return_value=["any"])
|
|
|
|
assert list(Package.local_files(Path("path"))) == [Path("local-file.tar.gz")]
|
|
|
|
|
|
def test_local_files_empty(mocker: MockerFixture, resource_path_root: Path) -> None:
|
|
"""
|
|
must extract empty local files list when there are no local files
|
|
"""
|
|
pkgbuild = resource_path_root / "models" / "package_yay_pkgbuild"
|
|
mocker.patch("ahriman.models.pkgbuild.Pkgbuild.from_file", return_value=Pkgbuild.from_file(pkgbuild))
|
|
mocker.patch("ahriman.models.package.Package.supported_architectures", return_value=["any"])
|
|
|
|
assert not list(Package.local_files(Path("path")))
|
|
|
|
|
|
def test_local_files_schema(mocker: MockerFixture, resource_path_root: Path) -> None:
|
|
"""
|
|
must skip local file source when file schema is used
|
|
"""
|
|
pkgbuild = resource_path_root / "models" / "package_yay_pkgbuild"
|
|
parsed_pkgbuild = Pkgbuild.from_file(pkgbuild)
|
|
parsed_pkgbuild.fields["source"] = PkgbuildPatch("source", ["file:///local-file.tar.gz"])
|
|
mocker.patch("ahriman.models.pkgbuild.Pkgbuild.from_file", return_value=parsed_pkgbuild)
|
|
mocker.patch("ahriman.models.package.Package.supported_architectures", return_value=["any"])
|
|
|
|
assert not list(Package.local_files(Path("path")))
|
|
|
|
|
|
def test_local_files_with_install(mocker: MockerFixture, resource_path_root: Path) -> None:
|
|
"""
|
|
must extract local file sources with install file
|
|
"""
|
|
pkgbuild = resource_path_root / "models" / "package_yay_pkgbuild"
|
|
parsed_pkgbuild = Pkgbuild.from_file(pkgbuild)
|
|
parsed_pkgbuild.fields["install"] = PkgbuildPatch("install", "install")
|
|
mocker.patch("ahriman.models.pkgbuild.Pkgbuild.from_file", return_value=parsed_pkgbuild)
|
|
mocker.patch("ahriman.models.package.Package.supported_architectures", return_value=["any"])
|
|
|
|
assert list(Package.local_files(Path("path"))) == [Path("install")]
|
|
|
|
|
|
def test_supported_architectures(mocker: MockerFixture, resource_path_root: Path) -> None:
|
|
"""
|
|
must generate list of available architectures
|
|
"""
|
|
pkgbuild = resource_path_root / "models" / "package_yay_pkgbuild"
|
|
mocker.patch("ahriman.models.pkgbuild.Pkgbuild.from_file", return_value=Pkgbuild.from_file(pkgbuild))
|
|
assert Package.supported_architectures(Path("path")) == \
|
|
{"i686", "pentium4", "x86_64", "arm", "armv7h", "armv6h", "aarch64", "riscv64"}
|
|
|
|
|
|
def test_actual_version(package_ahriman: Package, configuration: Configuration) -> None:
|
|
"""
|
|
must return same actual_version as version is
|
|
"""
|
|
assert package_ahriman.actual_version(configuration) == package_ahriman.version
|
|
|
|
|
|
def test_actual_version_vcs(package_tpacpi_bat_git: Package, configuration: Configuration,
|
|
mocker: MockerFixture, resource_path_root: Path) -> None:
|
|
"""
|
|
must return valid actual_version for VCS package
|
|
"""
|
|
pkgbuild = resource_path_root / "models" / "package_tpacpi-bat-git_pkgbuild"
|
|
mocker.patch("ahriman.models.pkgbuild.Pkgbuild.from_file", return_value=Pkgbuild.from_file(pkgbuild))
|
|
mocker.patch("pathlib.Path.glob", return_value=[Path("local")])
|
|
init_mock = mocker.patch("ahriman.core.build_tools.task.Task.init")
|
|
unlink_mock = mocker.patch("pathlib.Path.unlink")
|
|
|
|
assert package_tpacpi_bat_git.actual_version(configuration) == "3.1.r13.g4959b52-1"
|
|
init_mock.assert_called_once_with(configuration.repository_paths.cache_for(package_tpacpi_bat_git.base), [], None)
|
|
unlink_mock.assert_called_once_with()
|
|
|
|
|
|
def test_actual_version_failed(package_tpacpi_bat_git: Package, configuration: Configuration,
|
|
mocker: MockerFixture) -> None:
|
|
"""
|
|
must return same version in case if exception occurred
|
|
"""
|
|
mocker.patch("ahriman.core.build_tools.task.Task.init", side_effect=Exception())
|
|
mocker.patch("pathlib.Path.glob", return_value=[Path("local")])
|
|
unlink_mock = mocker.patch("pathlib.Path.unlink")
|
|
|
|
assert package_tpacpi_bat_git.actual_version(configuration) == package_tpacpi_bat_git.version
|
|
unlink_mock.assert_called_once_with()
|
|
|
|
|
|
def test_full_depends(package_ahriman: Package, package_python_schedule: Package, pyalpm_package_ahriman: MagicMock,
|
|
pyalpm_handle: MagicMock) -> None:
|
|
"""
|
|
must extract all dependencies from the package
|
|
"""
|
|
package_python_schedule.packages[package_python_schedule.base].provides = ["python3-schedule"]
|
|
|
|
database_mock = MagicMock()
|
|
database_mock.pkgcache = [pyalpm_package_ahriman]
|
|
pyalpm_handle.handle.get_syncdbs.return_value = [database_mock]
|
|
|
|
assert package_ahriman.full_depends(pyalpm_handle, [package_python_schedule]) == package_ahriman.depends
|
|
|
|
package_python_schedule.packages[package_python_schedule.base].depends = [package_ahriman.base]
|
|
expected = sorted(set(package_python_schedule.depends + package_ahriman.depends))
|
|
assert package_python_schedule.full_depends(pyalpm_handle, [package_python_schedule]) == expected
|
|
|
|
|
|
def test_is_newer_than(package_ahriman: Package, package_python_schedule: Package) -> None:
|
|
"""
|
|
must correctly check if package is newer than specified timestamp
|
|
"""
|
|
# base checks, true/false
|
|
assert package_ahriman.is_newer_than(package_ahriman.packages[package_ahriman.base].build_date - 1)
|
|
assert not package_ahriman.is_newer_than(package_ahriman.packages[package_ahriman.base].build_date + 1)
|
|
|
|
# list check
|
|
min_date = min(package.build_date for package in package_python_schedule.packages.values())
|
|
assert package_python_schedule.is_newer_than(min_date)
|
|
|
|
# null list check
|
|
package_python_schedule.packages["python-schedule"].build_date = None
|
|
assert package_python_schedule.is_newer_than(min_date)
|
|
|
|
package_python_schedule.packages["python2-schedule"].build_date = None
|
|
assert not package_python_schedule.is_newer_than(min_date)
|
|
|
|
|
|
def test_is_outdated_false(package_ahriman: Package, configuration: Configuration, mocker: MockerFixture) -> None:
|
|
"""
|
|
must be not outdated for the same package
|
|
"""
|
|
actual_version_mock = mocker.patch("ahriman.models.package.Package.actual_version",
|
|
return_value=package_ahriman.version)
|
|
assert not package_ahriman.is_outdated(package_ahriman, configuration)
|
|
actual_version_mock.assert_called_once_with(configuration)
|
|
|
|
|
|
def test_is_outdated_true(package_ahriman: Package, configuration: Configuration, mocker: MockerFixture) -> None:
|
|
"""
|
|
must be outdated for the new version
|
|
"""
|
|
other = Package.from_json(package_ahriman.view())
|
|
other.version = other.version.replace("-1", "-2")
|
|
actual_version_mock = mocker.patch("ahriman.models.package.Package.actual_version", return_value=other.version)
|
|
|
|
assert package_ahriman.is_outdated(other, configuration)
|
|
actual_version_mock.assert_called_once_with(configuration)
|
|
|
|
|
|
def test_is_outdated_no_version_calculation(package_ahriman: Package, configuration: Configuration,
|
|
mocker: MockerFixture) -> None:
|
|
"""
|
|
must not call actual version if calculation is disabled
|
|
"""
|
|
actual_version_mock = mocker.patch("ahriman.models.package.Package.actual_version")
|
|
assert not package_ahriman.is_outdated(package_ahriman, configuration, calculate_version=False)
|
|
actual_version_mock.assert_not_called()
|
|
|
|
|
|
def test_is_outdated_fresh_package(package_ahriman: Package, configuration: Configuration,
|
|
mocker: MockerFixture) -> None:
|
|
"""
|
|
must not call actual version if package is never than specified time
|
|
"""
|
|
configuration.set_option("build", "vcs_allowed_age", str(int(utcnow().timestamp())))
|
|
actual_version_mock = mocker.patch("ahriman.models.package.Package.actual_version")
|
|
assert not package_ahriman.is_outdated(package_ahriman, configuration)
|
|
actual_version_mock.assert_not_called()
|
|
|
|
|
|
def test_next_pkgrel(package_ahriman: Package) -> None:
|
|
"""
|
|
must correctly bump pkgrel
|
|
"""
|
|
assert package_ahriman.next_pkgrel(package_ahriman.version) == "1.1"
|
|
|
|
package_ahriman.version = "1.0.0-1.1"
|
|
assert package_ahriman.next_pkgrel(package_ahriman.version) == "1.2"
|
|
|
|
package_ahriman.version = "1.0.0-1.2.1"
|
|
assert package_ahriman.next_pkgrel(package_ahriman.version) == "1.2.2"
|
|
|
|
package_ahriman.version = "1:1.0.0-1"
|
|
assert package_ahriman.next_pkgrel("1:1.0.1-1") == "1.1"
|
|
assert package_ahriman.next_pkgrel("2:1.0.0-1") == "1.1"
|
|
|
|
package_ahriman.version = "1.0.0-1.1"
|
|
assert package_ahriman.next_pkgrel("1.0.1-2") == "2.1"
|
|
assert package_ahriman.next_pkgrel("1.0.0-2") == "2.1"
|
|
|
|
package_ahriman.version = "1.0.0-2"
|
|
assert package_ahriman.next_pkgrel("1.0.0-1.1") is None
|
|
|
|
assert package_ahriman.next_pkgrel(None) is None
|
|
|
|
|
|
def test_build_status_pretty_print(package_ahriman: Package) -> None:
|
|
"""
|
|
must return string in pretty print function
|
|
"""
|
|
assert package_ahriman.pretty_print()
|
|
assert isinstance(package_ahriman.pretty_print(), str)
|
|
|
|
|
|
def test_with_packages(package_ahriman: Package, package_python_schedule: Package, pacman: Pacman,
|
|
mocker: MockerFixture) -> None:
|
|
"""
|
|
must correctly replace packages descriptions
|
|
"""
|
|
paths = [Path("1"), Path("2")]
|
|
from_archive_mock = mocker.patch("ahriman.models.package.Package.from_archive", side_effect=[
|
|
package_ahriman, package_python_schedule
|
|
])
|
|
|
|
result = copy.deepcopy(package_ahriman)
|
|
package_ahriman.packages[package_ahriman.base].architecture = "i686"
|
|
|
|
result.with_packages(paths, pacman)
|
|
from_archive_mock.assert_has_calls([
|
|
MockCall(path, pacman) for path in paths
|
|
])
|
|
assert result.packages[result.base] == package_ahriman.packages[package_ahriman.base]
|