reorder tests

This commit is contained in:
2026-07-16 23:07:33 +03:00
parent d02ed8627d
commit a9767c3583
800 changed files with 307 additions and 996 deletions
@@ -0,0 +1,103 @@
import pytest
from pytest_mock import MockerFixture
from ahriman.application.application import Application
from ahriman.application.application.application_packages import ApplicationPackages
from ahriman.application.application.application_properties import ApplicationProperties
from ahriman.application.application.application_repository import ApplicationRepository
from ahriman.application.application.updates_iterator import FixedUpdatesIterator, UpdatesIterator
from ahriman.core.configuration import Configuration
from ahriman.core.database import SQLite
from ahriman.core.repository import Repository
@pytest.fixture
def application_packages(configuration: Configuration, database: SQLite, repository: Repository,
mocker: MockerFixture) -> ApplicationPackages:
"""
fixture for application with package functions
Args:
configuration(Configuration): configuration fixture
database(SQLite): database fixture
repository(Repository): repository fixture
mocker(MockerFixture): mocker object
Returns:
ApplicationPackages: application test instance
"""
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
_, repository_id = configuration.check_loaded()
return ApplicationPackages(repository_id, configuration, report=False)
@pytest.fixture
def application_properties(configuration: Configuration, database: SQLite, repository: Repository,
mocker: MockerFixture) -> ApplicationProperties:
"""
fixture for application with properties only
Args:
configuration(Configuration): configuration fixture
database(SQLite): database fixture
repository(Repository): repository fixture
mocker(MockerFixture): mocker object
Returns:
ApplicationProperties: application test instance
"""
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
_, repository_id = configuration.check_loaded()
return ApplicationProperties(repository_id, configuration, report=False)
@pytest.fixture
def application_repository(configuration: Configuration, database: SQLite, repository: Repository,
mocker: MockerFixture) -> ApplicationRepository:
"""
fixture for application with repository functions
Args:
configuration(Configuration): configuration fixture
database(SQLite): database fixture
repository(Repository): repository fixture
mocker(MockerFixture): mocker object
Returns:
ApplicationRepository: application test instance
"""
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
_, repository_id = configuration.check_loaded()
return ApplicationRepository(repository_id, configuration, report=False)
@pytest.fixture
def fixed_updates_iterator(application: Application) -> FixedUpdatesIterator:
"""
fixture for fixed updates iterator
Args:
application(Application): application fixture
Returns:
FixedUpdatesIterator: fixed updates iterator test instance
"""
return FixedUpdatesIterator(application, 1)
@pytest.fixture
def updates_iterator(application: Application) -> UpdatesIterator:
"""
fixture for chunk bases updates iterator
Args:
application(Application): application fixture
Returns:
UpdatesIterator: updates iterator test instance
"""
return UpdatesIterator(application, 1)
@@ -0,0 +1,164 @@
from pathlib import Path
from pytest_mock import MockerFixture
from typing import Any
from unittest.mock import MagicMock, call as MockCall
from ahriman.application.application import Application
from ahriman.core.tree import Leaf, Tree
from ahriman.models.package import Package
from ahriman.models.result import Result
def test_known_packages(application: Application, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must return not empty list of known packages
"""
mocker.patch("ahriman.core.repository.repository.Repository.packages", return_value=[package_ahriman])
packages = application._known_packages()
assert len(packages) > 1
assert package_ahriman.base in packages
def test_on_result(application: Application, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must call on_result trigger function
"""
mocker.patch("ahriman.core.repository.Repository.packages", return_value=[package_ahriman])
triggers_mock = mocker.patch("ahriman.core.triggers.TriggerLoader.on_result")
application.on_result(Result())
triggers_mock.assert_called_once_with(Result(), [package_ahriman])
def test_on_start(application: Application, mocker: MockerFixture) -> None:
"""
must call on_start trigger function
"""
triggers_mock = mocker.patch("ahriman.core.triggers.TriggerLoader.on_start")
application.on_start()
triggers_mock.assert_called_once_with()
def test_on_stop(application: Application, mocker: MockerFixture) -> None:
"""
must call on_stop trigger function
"""
triggers_mock = mocker.patch("ahriman.core.triggers.TriggerLoader.on_stop")
application.on_stop()
triggers_mock.assert_called_once_with()
def test_print_updates(application: Application, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must print updates
"""
tree = Tree([Leaf(package_ahriman)])
mocker.patch("ahriman.core.repository.repository.Repository.packages", return_value=[package_ahriman])
mocker.patch("ahriman.core.tree.Tree.resolve", return_value=tree.levels())
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
application.print_updates([package_ahriman], log_fn=print)
print_mock.assert_called_once_with(verbose=True, log_fn=print, separator=" -> ")
def test_with_dependencies(application: Application, package_ahriman: Package, package_python_schedule: Package,
mocker: MockerFixture) -> None:
"""
must append list of missing dependencies
"""
def create_package_mock(package_base) -> MagicMock:
mock = MagicMock()
mock.base = package_base
mock.depends_build = []
mock.packages_full = [package_base]
return mock
def get_package(name: str | Path, *args: Any, **kwargs: Any) -> Package:
name = name if isinstance(name, str) else name.name
return packages[name]
package_python_schedule.packages = {
package_python_schedule.base: package_python_schedule.packages[package_python_schedule.base]
}
package_ahriman.packages[package_ahriman.base].depends = ["devtools", "python", package_python_schedule.base]
package_ahriman.packages[package_ahriman.base].make_depends = ["python-build", "python-installer"]
packages = {
package_ahriman.base: package_ahriman,
package_python_schedule.base: package_python_schedule,
"python": create_package_mock("python"),
"python-installer": create_package_mock("python-installer"),
}
mocker.patch("pathlib.Path.is_dir", autospec=True, side_effect=lambda p: p.name == "python")
package_aur_mock = mocker.patch("ahriman.models.package.Package.from_aur", side_effect=get_package)
package_local_mock = mocker.patch("ahriman.models.package.Package.from_build", side_effect=get_package)
packages_mock = mocker.patch("ahriman.application.application.Application._known_packages",
return_value={"devtools", "python-build", "python-pytest"})
status_client_mock = mocker.patch("ahriman.core.status.Client.set_unknown")
result = application.with_dependencies([package_ahriman], process_dependencies=True)
assert {package.base: package for package in result} == packages
package_aur_mock.assert_has_calls([
MockCall(package_python_schedule.base, package_ahriman.packager, include_provides=True),
MockCall("python-installer", package_ahriman.packager, include_provides=True),
], any_order=True)
package_local_mock.assert_has_calls([
MockCall(application.repository.paths.cache_for("python"), "x86_64", package_ahriman.packager),
], any_order=True)
packages_mock.assert_called_once_with()
status_client_mock.assert_has_calls([
MockCall(package_python_schedule),
MockCall(packages["python"]),
MockCall(packages["python-installer"]),
], any_order=True)
def test_with_dependencies_exception(application: Application, package_ahriman: Package,
package_python_schedule: Package, mocker: MockerFixture) -> None:
"""
must skip packages if exception occurs
"""
def create_package_mock(package_base) -> MagicMock:
mock = MagicMock()
mock.base = package_base
mock.depends_build = []
mock.packages_full = [package_base]
return mock
package_python_schedule.packages = {
package_python_schedule.base: package_python_schedule.packages[package_python_schedule.base]
}
package_ahriman.packages[package_ahriman.base].depends = ["devtools", "python", package_python_schedule.base]
package_ahriman.packages[package_ahriman.base].make_depends = ["python-build", "python-installer"]
packages = {
package_ahriman.base: package_ahriman,
package_python_schedule.base: package_python_schedule,
"python": create_package_mock("python"),
"python-installer": create_package_mock("python-installer"),
}
mocker.patch("pathlib.Path.is_dir", autospec=True, side_effect=lambda p: p.name == "python")
mocker.patch("ahriman.models.package.Package.from_aur", side_effect=lambda *args: packages[args[0]])
mocker.patch("ahriman.models.package.Package.from_build", side_effect=Exception)
mocker.patch("ahriman.application.application.Application._known_packages",
return_value={"devtools", "python-build", "python-pytest"})
assert not application.with_dependencies([package_ahriman], process_dependencies=True)
def test_with_dependencies_skip(application: Application, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must skip processing of dependencies
"""
packages_mock = mocker.patch("ahriman.application.application.Application._known_packages")
assert application.with_dependencies([package_ahriman], process_dependencies=False) == [package_ahriman]
packages_mock.assert_not_called()
assert application.with_dependencies([], process_dependencies=True) == []
packages_mock.assert_not_called()
@@ -0,0 +1,236 @@
import pytest
from pathlib import Path
from pytest_mock import MockerFixture
from unittest.mock import MagicMock
from ahriman.application.application.application_packages import ApplicationPackages
from ahriman.core.exceptions import UnknownPackageError
from ahriman.models.package import Package
from ahriman.models.package_description import PackageDescription
from ahriman.models.package_source import PackageSource
from ahriman.models.result import Result
def test_add_archive(application_packages: ApplicationPackages, package_ahriman: Package,
mocker: MockerFixture) -> None:
"""
must add package from archive
"""
is_file_mock = mocker.patch("pathlib.Path.is_file", return_value=True)
copy_mock = mocker.patch("shutil.copy")
application_packages._add_archive(package_ahriman.base)
is_file_mock.assert_called_once_with()
copy_mock.assert_called_once_with(
Path(package_ahriman.base), application_packages.repository.paths.packages / package_ahriman.base)
def test_add_archive_missing(application_packages: ApplicationPackages, mocker: MockerFixture) -> None:
"""
must raise UnknownPackageError on unknown path
"""
mocker.patch("pathlib.Path.is_file", return_value=False)
with pytest.raises(UnknownPackageError):
application_packages._add_archive("package")
def test_add_aur(application_packages: ApplicationPackages, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must add package from AUR
"""
mocker.patch("ahriman.models.package.Package.from_aur", return_value=package_ahriman)
build_queue_mock = mocker.patch("ahriman.core.database.SQLite.build_queue_insert")
status_client_mock = mocker.patch("ahriman.core.status.Client.set_unknown")
application_packages._add_aur(package_ahriman.base, "packager")
build_queue_mock.assert_called_once_with(package_ahriman)
status_client_mock.assert_called_once_with(package_ahriman)
def test_add_directory(application_packages: ApplicationPackages, package_ahriman: Package,
mocker: MockerFixture) -> None:
"""
must add packages from directory
"""
is_dir_mock = mocker.patch("pathlib.Path.is_dir", return_value=True)
filename = package_ahriman.packages[package_ahriman.base].filepath
iterdir_mock = mocker.patch("pathlib.Path.iterdir", return_value=[filename])
add_mock = mocker.patch("ahriman.application.application.application_packages.ApplicationPackages._add_archive")
application_packages._add_directory(package_ahriman.base)
is_dir_mock.assert_called_once_with()
iterdir_mock.assert_called_once_with()
add_mock.assert_called_once_with(str(filename))
def test_add_directory_missing(application_packages: ApplicationPackages, mocker: MockerFixture) -> None:
"""
must raise UnknownPackageError on unknown directory path
"""
mocker.patch("pathlib.Path.is_dir", return_value=False)
with pytest.raises(UnknownPackageError):
application_packages._add_directory("package")
def test_add_local(application_packages: ApplicationPackages, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must add package from local sources
"""
mocker.patch("ahriman.models.package.Package.from_build", return_value=package_ahriman)
is_dir_mock = mocker.patch("pathlib.Path.is_dir", return_value=True)
init_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.init")
copytree_mock = mocker.patch("shutil.copytree")
build_queue_mock = mocker.patch("ahriman.core.database.SQLite.build_queue_insert")
application_packages._add_local(package_ahriman.base, "packager")
is_dir_mock.assert_called_once_with()
copytree_mock.assert_called_once_with(
Path(package_ahriman.base),
application_packages.repository.paths.cache_for(package_ahriman.base),
dirs_exist_ok=True)
init_mock.assert_called_once_with(application_packages.repository.paths.cache_for(package_ahriman.base))
build_queue_mock.assert_called_once_with(package_ahriman)
def test_add_local_cache(application_packages: ApplicationPackages, package_ahriman: Package,
mocker: MockerFixture) -> None:
"""
must add package from local source if there is cache
"""
mocker.patch("ahriman.models.package.Package.from_build", return_value=package_ahriman)
mocker.patch("pathlib.Path.is_dir", autospec=True,
side_effect=lambda p: p.is_relative_to(application_packages.repository.paths.cache))
init_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.init")
copytree_mock = mocker.patch("shutil.copytree")
build_queue_mock = mocker.patch("ahriman.core.database.SQLite.build_queue_insert")
application_packages._add_local(package_ahriman.base, "packager")
copytree_mock.assert_not_called()
init_mock.assert_not_called()
build_queue_mock.assert_called_once_with(package_ahriman)
def test_add_local_missing(application_packages: ApplicationPackages, mocker: MockerFixture) -> None:
"""
must raise UnknownPackageError if package wasn't found
"""
mocker.patch("pathlib.Path.is_dir", return_value=False)
with pytest.raises(UnknownPackageError):
application_packages._add_local("package", "packager")
def test_add_remote(application_packages: ApplicationPackages, package_description_ahriman: PackageDescription,
mocker: MockerFixture) -> None:
"""
must add package from remote source
"""
response_mock = MagicMock()
response_mock.iter_content.return_value = ["chunk"]
open_mock = mocker.patch("pathlib.Path.open")
request_mock = mocker.patch("requests.get", return_value=response_mock)
url = f"https://host/{package_description_ahriman.filename}"
application_packages._add_remote(url)
open_mock.assert_called_once_with("wb")
request_mock.assert_called_once_with(url, stream=True, timeout=None)
response_mock.raise_for_status.assert_called_once_with()
def test_add_remote_missing(application_packages: ApplicationPackages, mocker: MockerFixture) -> None:
"""
must raise UnknownPackageError if remote package wasn't found
"""
mocker.patch("requests.get", side_effect=Exception)
with pytest.raises(UnknownPackageError):
application_packages._add_remote("url")
def test_add_repository(application_packages: ApplicationPackages, package_ahriman: Package,
mocker: MockerFixture) -> None:
"""
must add package from official repository
"""
mocker.patch("ahriman.models.package.Package.from_official", return_value=package_ahriman)
build_queue_mock = mocker.patch("ahriman.core.database.SQLite.build_queue_insert")
status_client_mock = mocker.patch("ahriman.core.status.Client.set_unknown")
application_packages._add_repository(package_ahriman.base, "packager")
build_queue_mock.assert_called_once_with(package_ahriman)
status_client_mock.assert_called_once_with(package_ahriman)
def test_add_add_archive(application_packages: ApplicationPackages, package_ahriman: Package,
mocker: MockerFixture) -> None:
"""
must add package from archive via add function
"""
add_mock = mocker.patch("ahriman.application.application.application_packages.ApplicationPackages._add_archive")
application_packages.add([package_ahriman.base], PackageSource.Archive, "packager")
add_mock.assert_called_once_with(package_ahriman.base, "packager")
def test_add_add_aur(application_packages: ApplicationPackages, package_ahriman: Package,
mocker: MockerFixture) -> None:
"""
must add package from AUR via add function
"""
add_mock = mocker.patch("ahriman.application.application.application_packages.ApplicationPackages._add_aur")
application_packages.add([package_ahriman.base], PackageSource.AUR, "packager")
add_mock.assert_called_once_with(package_ahriman.base, "packager")
def test_add_add_directory(application_packages: ApplicationPackages, package_ahriman: Package,
mocker: MockerFixture) -> None:
"""
must add packages from directory via add function
"""
add_mock = mocker.patch("ahriman.application.application.application_packages.ApplicationPackages._add_directory")
application_packages.add([package_ahriman.base], PackageSource.Directory, "packager")
add_mock.assert_called_once_with(package_ahriman.base, "packager")
def test_add_add_local(application_packages: ApplicationPackages, package_ahriman: Package,
mocker: MockerFixture) -> None:
"""
must add package from local sources via add function
"""
add_mock = mocker.patch("ahriman.application.application.application_packages.ApplicationPackages._add_local")
application_packages.add([package_ahriman.base], PackageSource.Local, "packager")
add_mock.assert_called_once_with(package_ahriman.base, "packager")
def test_add_add_remote(application_packages: ApplicationPackages, package_description_ahriman: PackageDescription,
mocker: MockerFixture) -> None:
"""
must add package from remote source via add function
"""
add_mock = mocker.patch("ahriman.application.application.application_packages.ApplicationPackages._add_remote")
url = f"https://host/{package_description_ahriman.filename}"
application_packages.add([url], PackageSource.Remote, "packager")
add_mock.assert_called_once_with(url, "packager")
def test_on_result(application_packages: ApplicationPackages) -> None:
"""
must raise NotImplemented for missing finalize method
"""
with pytest.raises(NotImplementedError):
application_packages.on_result(Result())
def test_remove(application_packages: ApplicationPackages, mocker: MockerFixture) -> None:
"""
must remove package
"""
executor_mock = mocker.patch("ahriman.core.repository.executor.Executor.process_remove", return_value=Result())
on_result_mock = mocker.patch("ahriman.application.application.application_packages.ApplicationPackages.on_result")
application_packages.remove([])
executor_mock.assert_called_once_with([])
on_result_mock.assert_called_once_with(Result())
@@ -0,0 +1,15 @@
from ahriman.application.application.application_properties import ApplicationProperties
def test_architecture(application_properties: ApplicationProperties) -> None:
"""
must return repository architecture
"""
assert application_properties.architecture == application_properties.repository_id.architecture
def test_reporter(application_properties: ApplicationProperties) -> None:
"""
must have reporter attribute
"""
assert application_properties.reporter
@@ -0,0 +1,404 @@
import pytest
from pathlib import Path
from pytest_mock import MockerFixture
from unittest.mock import call as MockCall
from ahriman.application.application.application_repository import ApplicationRepository
from ahriman.core.exceptions import UnknownPackageError
from ahriman.core.tree import Leaf, Tree
from ahriman.models.changes import Changes
from ahriman.models.package import Package
from ahriman.models.packagers import Packagers
from ahriman.models.result import Result
def test_changes(application_repository: ApplicationRepository, package_ahriman: Package,
mocker: MockerFixture) -> None:
"""
must generate changes for the packages
"""
changes = Changes("sha", "change")
hashes_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_changes_get", return_value=changes)
changes_mock = mocker.patch("ahriman.core.repository.Repository.package_changes", return_value=changes)
report_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_changes_update")
application_repository.changes([package_ahriman])
hashes_mock.assert_called_once_with(package_ahriman.base)
changes_mock.assert_called_once_with(package_ahriman, changes.last_commit_sha)
report_mock.assert_called_once_with(package_ahriman.base, changes)
def test_changes_skip(application_repository: ApplicationRepository, package_ahriman: Package,
mocker: MockerFixture) -> None:
"""
must skip change generation if no last commit sha has been found
"""
changes_mock = mocker.patch("ahriman.core.repository.Repository.package_changes")
report_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_changes_update")
application_repository.changes([package_ahriman])
changes_mock.assert_not_called()
report_mock.assert_not_called()
def test_changes_no_update(application_repository: ApplicationRepository, package_ahriman: Package,
mocker: MockerFixture) -> None:
"""
must skip update if package_changes returns None (no new commits)
"""
changes = Changes("sha", "change")
mocker.patch("ahriman.core.status.local_client.LocalClient.package_changes_get", return_value=changes)
mocker.patch("ahriman.core.repository.Repository.package_changes", return_value=None)
report_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_changes_update")
application_repository.changes([package_ahriman])
report_mock.assert_not_called()
def test_clean_cache(application_repository: ApplicationRepository, mocker: MockerFixture) -> None:
"""
must clean cache directory
"""
clear_mock = mocker.patch("ahriman.core.repository.Repository.clear_cache")
application_repository.clean(cache=True, chroot=False, manual=False, packages=False, pacman=False)
clear_mock.assert_called_once_with()
def test_clean_chroot(application_repository: ApplicationRepository, mocker: MockerFixture) -> None:
"""
must clean chroot directory
"""
clear_mock = mocker.patch("ahriman.core.repository.Repository.clear_chroot")
application_repository.clean(cache=False, chroot=True, manual=False, packages=False, pacman=False)
clear_mock.assert_called_once_with()
def test_clean_manual(application_repository: ApplicationRepository, mocker: MockerFixture) -> None:
"""
must clean manual directory
"""
clear_mock = mocker.patch("ahriman.core.repository.Repository.clear_queue")
application_repository.clean(cache=False, chroot=False, manual=True, packages=False, pacman=False)
clear_mock.assert_called_once_with()
def test_clean_packages(application_repository: ApplicationRepository, mocker: MockerFixture) -> None:
"""
must clean packages directory
"""
clear_mock = mocker.patch("ahriman.core.repository.Repository.clear_packages")
application_repository.clean(cache=False, chroot=False, manual=False, packages=True, pacman=False)
clear_mock.assert_called_once_with()
def test_clean_pacman(application_repository: ApplicationRepository, mocker: MockerFixture) -> None:
"""
must clean pacman directory
"""
clear_mock = mocker.patch("ahriman.core.repository.Repository.clear_pacman")
application_repository.clean(cache=False, chroot=False, manual=False, packages=False, pacman=True)
clear_mock.assert_called_once_with()
def test_on_result(application_repository: ApplicationRepository) -> None:
"""
must raise NotImplemented for missing finalize method
"""
with pytest.raises(NotImplementedError):
application_repository.on_result(Result())
def test_sign(application_repository: ApplicationRepository, package_ahriman: Package, package_python_schedule: Package,
mocker: MockerFixture) -> None:
"""
must sign world
"""
mocker.patch("ahriman.core.repository.repository.Repository.packages",
return_value=[package_ahriman, package_python_schedule])
sign_package_mock = mocker.patch("ahriman.core.sign.gpg.GPG.process_sign_package")
sign_repository_mock = mocker.patch("ahriman.core.sign.gpg.GPG.process_sign_repository")
on_result_mock = mocker.patch(
"ahriman.application.application.application_repository.ApplicationRepository.on_result")
application_repository.sign([])
sign_package_mock.assert_has_calls([
MockCall(pytest.helpers.anyvar(int), None),
MockCall(pytest.helpers.anyvar(int), None),
MockCall(pytest.helpers.anyvar(int), None),
])
sign_repository_mock.assert_called_once_with(application_repository.repository.repo.repo_path)
on_result_mock.assert_called_once_with(Result())
def test_sign_skip(application_repository: ApplicationRepository, package_ahriman: Package,
mocker: MockerFixture) -> None:
"""
must skip sign packages with empty filename
"""
package_ahriman.packages[package_ahriman.base].filename = None
mocker.patch("ahriman.core.repository.repository.Repository.packages", return_value=[package_ahriman])
mocker.patch("ahriman.application.application.application_repository.ApplicationRepository.update")
mocker.patch("ahriman.application.application.application_repository.ApplicationRepository.on_result")
application_repository.sign([])
def test_unknown_no_aur(application_repository: ApplicationRepository, package_ahriman: Package,
mocker: MockerFixture) -> None:
"""
must return empty list in case if there is locally stored PKGBUILD
"""
mocker.patch("ahriman.core.repository.repository.Repository.packages", return_value=[package_ahriman])
mocker.patch("ahriman.models.package.Package.from_aur", side_effect=UnknownPackageError(package_ahriman.base))
mocker.patch("ahriman.models.package.Package.from_build", return_value=package_ahriman)
mocker.patch("pathlib.Path.is_dir", return_value=True)
mocker.patch("ahriman.core.build_tools.sources.Sources.has_remotes", return_value=False)
assert not application_repository.unknown()
def test_unknown_no_aur_no_local(application_repository: ApplicationRepository, package_ahriman: Package,
mocker: MockerFixture) -> None:
"""
must return list of packages missing in aur and in local storage
"""
mocker.patch("ahriman.core.repository.repository.Repository.packages", return_value=[package_ahriman])
mocker.patch("ahriman.models.package.Package.from_aur", side_effect=UnknownPackageError(package_ahriman.base))
mocker.patch("pathlib.Path.is_dir", return_value=False)
packages = application_repository.unknown()
assert packages == list(package_ahriman.packages.keys())
def test_unknown_no_local(application_repository: ApplicationRepository, package_ahriman: Package,
mocker: MockerFixture) -> None:
"""
must return empty list in case if there is package in AUR
"""
mocker.patch("ahriman.core.repository.repository.Repository.packages", return_value=[package_ahriman])
mocker.patch("ahriman.models.package.Package.from_aur")
mocker.patch("pathlib.Path.is_dir", return_value=False)
assert not application_repository.unknown()
def test_update(application_repository: ApplicationRepository, package_ahriman: Package, result: Result,
mocker: MockerFixture) -> None:
"""
must process package updates
"""
paths = [package.filepath for package in package_ahriman.packages.values()]
tree = Tree([Leaf(package_ahriman)])
prebuilt_result = Result()
resolve_mock = mocker.patch("ahriman.application.application.workers.local_updater.LocalUpdater.partition",
return_value=tree.levels())
mocker.patch("ahriman.core.repository.repository.Repository.packages_built", return_value=paths)
build_mock = mocker.patch("ahriman.application.application.workers.local_updater.LocalUpdater.update",
return_value=result)
update_mock = mocker.patch("ahriman.core.repository.Repository.process_update", return_value=prebuilt_result)
on_result_mock = mocker.patch(
"ahriman.application.application.application_repository.ApplicationRepository.on_result")
application_repository.update([package_ahriman], Packagers("username"), bump_pkgrel=True)
resolve_mock.assert_called_once_with([package_ahriman])
build_mock.assert_called_once_with([package_ahriman], Packagers("username"), bump_pkgrel=True)
update_mock.assert_called_once_with(paths, Packagers("username"))
on_result_mock.assert_has_calls([MockCall(prebuilt_result), MockCall(result)])
def test_update_prebuilt_filter(application_repository: ApplicationRepository, package_ahriman: Package, result: Result,
mocker: MockerFixture) -> None:
"""
must filter out packages which were successfully prebuilt
"""
paths = [package.filepath for package in package_ahriman.packages.values()]
resolve_mock = mocker.patch("ahriman.application.application.workers.local_updater.LocalUpdater.partition",
return_value=[])
mocker.patch("ahriman.core.repository.repository.Repository.packages_built", return_value=paths)
mocker.patch("ahriman.core.repository.Repository.process_update", return_value=result)
mocker.patch("ahriman.application.application.application_repository.ApplicationRepository.on_result")
application_repository.update([package_ahriman], Packagers("username"), bump_pkgrel=True)
resolve_mock.assert_called_once_with([])
def test_update_empty(application_repository: ApplicationRepository, package_ahriman: Package, result: Result,
mocker: MockerFixture) -> None:
"""
must skip updating repository if no packages supplied
"""
tree = Tree([Leaf(package_ahriman)])
mocker.patch("ahriman.application.application.workers.Updater.partition", return_value=tree.levels())
mocker.patch("ahriman.core.repository.Repository.packages_built", return_value=[])
mocker.patch("ahriman.application.application.workers.local_updater.LocalUpdater.update", return_value=result)
mocker.patch("ahriman.application.application.application_repository.ApplicationRepository.on_result")
update_mock = mocker.patch("ahriman.core.repository.Repository.process_update")
application_repository.update([package_ahriman])
update_mock.assert_not_called()
def test_updates_all(application_repository: ApplicationRepository, package_ahriman: Package,
mocker: MockerFixture) -> None:
"""
must get updates for all
"""
path = Path("local")
mocker.patch("ahriman.core.repository.package_info.PackageInfo.packages_built", return_value=[path])
updates_built_mock = mocker.patch("ahriman.core.repository.package_info.PackageInfo.load_archives")
updates_aur_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_aur",
return_value=[package_ahriman])
updates_local_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_local")
updates_manual_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_manual")
updates_deps_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_dependencies")
application_repository.updates([], aur=True, local=True, manual=True, vcs=True, check_files=True)
updates_built_mock.assert_called_once_with([path])
updates_aur_mock.assert_called_once_with([], vcs=True)
updates_local_mock.assert_called_once_with(vcs=True)
updates_manual_mock.assert_called_once_with()
updates_deps_mock.assert_called_once_with([])
def test_updates_disabled(application_repository: ApplicationRepository, mocker: MockerFixture) -> None:
"""
must get updates without anything
"""
path = Path("local")
mocker.patch("ahriman.core.repository.package_info.PackageInfo.packages_built", return_value=[path])
updates_built_mock = mocker.patch("ahriman.core.repository.package_info.PackageInfo.load_archives")
updates_aur_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_aur")
updates_local_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_local")
updates_manual_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_manual")
updates_deps_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_dependencies")
application_repository.updates([], aur=False, local=False, manual=False, vcs=True, check_files=False)
updates_built_mock.assert_called_once_with([path])
updates_aur_mock.assert_not_called()
updates_local_mock.assert_not_called()
updates_manual_mock.assert_not_called()
updates_deps_mock.assert_not_called()
def test_updates_no_aur(application_repository: ApplicationRepository, mocker: MockerFixture) -> None:
"""
must get updates without aur
"""
path = Path("local")
mocker.patch("ahriman.core.repository.package_info.PackageInfo.packages_built", return_value=[path])
updates_built_mock = mocker.patch("ahriman.core.repository.package_info.PackageInfo.load_archives")
updates_aur_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_aur")
updates_local_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_local")
updates_manual_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_manual")
updates_deps_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_dependencies")
application_repository.updates([], aur=False, local=True, manual=True, vcs=True, check_files=True)
updates_built_mock.assert_called_once_with([path])
updates_aur_mock.assert_not_called()
updates_local_mock.assert_called_once_with(vcs=True)
updates_manual_mock.assert_called_once_with()
updates_deps_mock.assert_called_once_with([])
def test_updates_no_local(application_repository: ApplicationRepository, mocker: MockerFixture) -> None:
"""
must get updates without local packages
"""
path = Path("local")
mocker.patch("ahriman.core.repository.package_info.PackageInfo.packages_built", return_value=[path])
updates_built_mock = mocker.patch("ahriman.core.repository.package_info.PackageInfo.load_archives")
updates_aur_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_aur")
updates_local_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_local")
updates_manual_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_manual")
updates_deps_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_dependencies")
application_repository.updates([], aur=True, local=False, manual=True, vcs=True, check_files=True)
updates_built_mock.assert_called_once_with([path])
updates_aur_mock.assert_called_once_with([], vcs=True)
updates_local_mock.assert_not_called()
updates_manual_mock.assert_called_once_with()
updates_deps_mock.assert_called_once_with([])
def test_updates_no_manual(application_repository: ApplicationRepository, mocker: MockerFixture) -> None:
"""
must get updates without manual
"""
path = Path("local")
mocker.patch("ahriman.core.repository.package_info.PackageInfo.packages_built", return_value=[path])
updates_built_mock = mocker.patch("ahriman.core.repository.package_info.PackageInfo.load_archives")
updates_aur_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_aur")
updates_local_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_local")
updates_manual_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_manual")
updates_deps_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_dependencies")
application_repository.updates([], aur=True, local=True, manual=False, vcs=True, check_files=True)
updates_built_mock.assert_called_once_with([path])
updates_aur_mock.assert_called_once_with([], vcs=True)
updates_local_mock.assert_called_once_with(vcs=True)
updates_manual_mock.assert_not_called()
updates_deps_mock.assert_called_once_with([])
def test_updates_no_vcs(application_repository: ApplicationRepository, mocker: MockerFixture) -> None:
"""
must get updates without VCS
"""
path = Path("local")
mocker.patch("ahriman.core.repository.package_info.PackageInfo.packages_built", return_value=[path])
updates_built_mock = mocker.patch("ahriman.core.repository.package_info.PackageInfo.load_archives")
updates_aur_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_aur")
updates_local_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_local")
updates_manual_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_manual")
updates_deps_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_dependencies")
application_repository.updates([], aur=True, local=True, manual=True, vcs=False, check_files=True)
updates_built_mock.assert_called_once_with([path])
updates_aur_mock.assert_called_once_with([], vcs=False)
updates_local_mock.assert_called_once_with(vcs=False)
updates_manual_mock.assert_called_once_with()
updates_deps_mock.assert_called_once_with([])
def test_updates_no_check_files(application_repository: ApplicationRepository, mocker: MockerFixture) -> None:
"""
must get updates without checking broken links
"""
path = Path("local")
mocker.patch("ahriman.core.repository.package_info.PackageInfo.packages_built", return_value=[path])
updates_built_mock = mocker.patch("ahriman.core.repository.package_info.PackageInfo.load_archives")
updates_aur_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_aur")
updates_local_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_local")
updates_manual_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_manual")
updates_deps_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_dependencies")
application_repository.updates([], aur=True, local=True, manual=True, vcs=True, check_files=False)
updates_built_mock.assert_called_once_with([path])
updates_aur_mock.assert_called_once_with([], vcs=True)
updates_local_mock.assert_called_once_with(vcs=True)
updates_manual_mock.assert_called_once_with()
updates_deps_mock.assert_not_called()
def test_updates_with_filter(application_repository: ApplicationRepository, mocker: MockerFixture) -> None:
"""
must get updates with filter
"""
path = Path("local")
mocker.patch("ahriman.core.repository.package_info.PackageInfo.packages_built", return_value=[path])
updates_built_mock = mocker.patch("ahriman.core.repository.package_info.PackageInfo.load_archives")
updates_aur_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_aur")
updates_local_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_local")
updates_manual_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_manual")
updates_deps_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_dependencies")
application_repository.updates(["filter"], aur=True, local=True, manual=True, vcs=True, check_files=True)
updates_built_mock.assert_called_once_with([path])
updates_aur_mock.assert_called_once_with(["filter"], vcs=True)
updates_local_mock.assert_called_once_with(vcs=True)
updates_manual_mock.assert_called_once_with()
updates_deps_mock.assert_called_once_with(["filter"])
@@ -0,0 +1,74 @@
from pytest_mock import MockerFixture
from unittest.mock import call as MockCall
from ahriman.application.application.updates_iterator import FixedUpdatesIterator, UpdatesIterator
from ahriman.models.package import Package
def test_select_packages(updates_iterator: UpdatesIterator, package_ahriman: Package,
package_python_schedule: Package, mocker: MockerFixture) -> None:
"""
must return next partition
"""
mocker.patch("ahriman.core.repository.Repository.packages",
return_value=[package_ahriman, package_python_schedule])
assert updates_iterator.select_packages() == ([package_python_schedule.base], 2)
assert updates_iterator.select_packages() == ([package_python_schedule.base], 2)
def test_select_packages_empty(updates_iterator: UpdatesIterator, mocker: MockerFixture) -> None:
"""
must return None for empty repository
"""
mocker.patch("ahriman.core.repository.Repository.packages", return_value=[])
assert updates_iterator.select_packages() == (None, 1)
def test_select_packages_cycle(updates_iterator: UpdatesIterator, package_ahriman: Package,
package_python_schedule: Package, mocker: MockerFixture) -> None:
"""
must cycle over partitions
"""
mocker.patch("ahriman.core.repository.Repository.packages",
return_value=[package_ahriman, package_python_schedule])
assert updates_iterator.select_packages() == ([package_python_schedule.base], 2)
updates_iterator.updated_packages.add(package_python_schedule.base)
assert updates_iterator.select_packages() == ([package_ahriman.base], 2)
updates_iterator.updated_packages.add(package_ahriman.base)
assert updates_iterator.select_packages() == ([package_python_schedule.base], 2)
assert not updates_iterator.updated_packages
def test_iter(updates_iterator: UpdatesIterator) -> None:
"""
must return self as iterator
"""
assert iter(updates_iterator) == updates_iterator
def test_next(updates_iterator: UpdatesIterator, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must return next chunk to update
"""
mocker.patch("ahriman.application.application.updates_iterator.UpdatesIterator.select_packages",
side_effect=[([package_ahriman.base], 2), (None, 2), StopIteration])
sleep_mock = mocker.patch("time.sleep")
updates = list(updates_iterator)
assert updates == [[package_ahriman.base], None]
sleep_mock.assert_has_calls([MockCall(0.5), MockCall(0.5)])
def test_fixed_updates_iterator(fixed_updates_iterator: FixedUpdatesIterator, package_ahriman: Package,
mocker: MockerFixture) -> None:
"""
must always return empty package list
"""
assert fixed_updates_iterator.select_packages() == ([], 1)
mocker.patch("ahriman.core.repository.Repository.packages", return_value=[package_ahriman])
assert fixed_updates_iterator.select_packages() == ([], 1)
@@ -0,0 +1,48 @@
import pytest
from ahriman.application.application.workers import Updater
from ahriman.application.application.workers.local_updater import LocalUpdater
from ahriman.application.application.workers.remote_updater import RemoteUpdater
from ahriman.core.configuration import Configuration
from ahriman.core.repository import Repository
from ahriman.models.worker import Worker
@pytest.fixture
def local_updater(repository: Repository) -> LocalUpdater:
"""
local updater fixture
Args:
repository(Repository): repository fixture
Returns:
LocalUpdater: local updater test instance
"""
return LocalUpdater(repository)
@pytest.fixture
def remote_updater(configuration: Configuration) -> RemoteUpdater:
"""
local updater fixture
Args:
configuration(Configuration): configuration fixture
Returns:
RemoteUpdater: remote updater test instance
"""
_, repository_id = configuration.check_loaded()
return RemoteUpdater([Worker("remote1"), Worker("remote2")], repository_id, configuration)
@pytest.fixture
def updater() -> Updater:
"""
empty updater fixture
Returns:
Updater: empty updater test instance
"""
return Updater()
@@ -0,0 +1,30 @@
from pytest_mock import MockerFixture
from ahriman.application.application.workers.local_updater import LocalUpdater
from ahriman.models.package import Package
from ahriman.models.packagers import Packagers
from ahriman.models.result import Result
def test_partition(local_updater: LocalUpdater, mocker: MockerFixture) -> None:
"""
must partition as tree resolution
"""
resolve_mock = mocker.patch("ahriman.core.tree.Tree.resolve")
local_updater.partition([])
resolve_mock.assert_called_once_with([])
def test_update(local_updater: LocalUpdater, package_ahriman: Package, result: Result,
mocker: MockerFixture) -> None:
"""
must process package updates
"""
paths = [package.filepath for package in package_ahriman.packages.values()]
mocker.patch("ahriman.core.repository.Repository.packages_built", return_value=paths)
build_mock = mocker.patch("ahriman.core.repository.Repository.process_build", return_value=result)
update_mock = mocker.patch("ahriman.core.repository.Repository.process_update", return_value=result)
assert local_updater.update([package_ahriman], Packagers("username"), bump_pkgrel=True) == result
build_mock.assert_called_once_with([package_ahriman], Packagers("username"), bump_pkgrel=True)
update_mock.assert_called_once_with(paths, Packagers("username"))
@@ -0,0 +1,83 @@
from pytest_mock import MockerFixture
from ahriman.application.application.workers.remote_updater import RemoteUpdater
from ahriman.core.http import SyncAhrimanClient
from ahriman.models.package import Package
from ahriman.models.packagers import Packagers
from ahriman.models.result import Result
def test_clients(remote_updater: RemoteUpdater) -> None:
"""
must return map of clients
"""
worker = remote_updater.workers[0]
client = SyncAhrimanClient()
remote_updater._clients.append((worker, client))
assert remote_updater.clients == {worker: client}
def test_update_url(remote_updater: RemoteUpdater) -> None:
"""
must generate update url correctly
"""
worker = remote_updater.workers[0]
assert remote_updater._update_url(worker).startswith(worker.address)
assert remote_updater._update_url(worker).endswith("/api/v1/service/add")
def test_next_worker(remote_updater: RemoteUpdater) -> None:
"""
must return next not used worker
"""
assert remote_updater.next_worker()[0] == remote_updater.workers[0]
assert len(remote_updater.clients) == 1
assert remote_updater.workers[0] in remote_updater.clients
assert remote_updater.next_worker()[0] == remote_updater.workers[1]
assert remote_updater.workers[1] in remote_updater.clients
assert len(remote_updater.clients) == 2
def test_next_worker_cycle(remote_updater: RemoteUpdater) -> None:
"""
must return first used worker if no free workers left
"""
worker1, client1 = remote_updater.next_worker()
worker2, client2 = remote_updater.next_worker()
assert remote_updater.next_worker() == (worker1, client1)
assert remote_updater.next_worker() == (worker2, client2)
assert remote_updater.next_worker() == (worker1, client1)
def test_partition(remote_updater: RemoteUpdater, mocker: MockerFixture) -> None:
"""
must partition as tree partition
"""
resolve_mock = mocker.patch("ahriman.core.tree.Tree.partition")
remote_updater.partition([])
resolve_mock.assert_called_once_with([], count=2)
def test_update(remote_updater: RemoteUpdater, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must process remote package updates
"""
worker, client = remote_updater.next_worker()
worker_mock = mocker.patch("ahriman.application.application.workers.remote_updater.RemoteUpdater.next_worker",
return_value=(worker, client))
request_mock = mocker.patch("ahriman.core.http.SyncAhrimanClient.make_request")
assert remote_updater.update([package_ahriman], Packagers("username"), bump_pkgrel=True) == Result()
worker_mock.assert_called_once_with()
request_mock.assert_called_once_with("POST", remote_updater._update_url(worker),
params=remote_updater.repository_id.query(),
json={
"increment": False,
"packager": "username",
"packages": [package_ahriman.base],
"patches": [],
"refresh": True,
})
@@ -0,0 +1,50 @@
import pytest
from ahriman.application.application.workers import Updater
from ahriman.application.application.workers.local_updater import LocalUpdater
from ahriman.application.application.workers.remote_updater import RemoteUpdater
from ahriman.core.configuration import Configuration
from ahriman.core.repository import Repository
from ahriman.models.worker import Worker
def test_load(configuration: Configuration, repository: Repository) -> None:
"""
must load local updater if empty worker list is set
"""
_, repository_id = configuration.check_loaded()
assert isinstance(Updater.load(repository_id, configuration, repository), LocalUpdater)
assert isinstance(Updater.load(repository_id, configuration, repository, []), LocalUpdater)
def test_load_from_option(configuration: Configuration, repository: Repository) -> None:
"""
must load remote updater if nonempty worker list is set
"""
_, repository_id = configuration.check_loaded()
assert isinstance(Updater.load(repository_id, configuration, repository, [Worker("remote")]), RemoteUpdater)
def test_load_from_configuration(configuration: Configuration, repository: Repository) -> None:
"""
must load remote updater from settings
"""
configuration.set_option("build", "workers", "remote")
_, repository_id = configuration.check_loaded()
assert isinstance(Updater.load(repository_id, configuration, repository), RemoteUpdater)
def test_partition(updater: Updater) -> None:
"""
must raise not implemented error for missing partition method
"""
with pytest.raises(NotImplementedError):
updater.partition([])
def test_update(updater: Updater) -> None:
"""
must raise not implemented error for missing update method
"""
with pytest.raises(NotImplementedError):
updater.update([])
@@ -0,0 +1,83 @@
import argparse
import pytest
from pytest_mock import MockerFixture
from ahriman.application.ahriman import _parser
from ahriman.application.application import Application
from ahriman.application.help_formatter import _HelpFormatter
from ahriman.application.lock import Lock
from ahriman.core.configuration import Configuration
from ahriman.core.database import SQLite
from ahriman.core.repository import Repository
@pytest.fixture
def application(configuration: Configuration, repository: Repository, database: SQLite,
mocker: MockerFixture) -> Application:
"""
fixture for application
Args:
configuration(Configuration): configuration fixture
database(SQLite): database fixture
repository(Repository): repository fixture
mocker(MockerFixture): mocker object
Returns:
Application: application test instance
"""
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
_, repository_id = configuration.check_loaded()
return Application(repository_id, configuration, report=False)
@pytest.fixture
def args() -> argparse.Namespace:
"""
fixture for command line arguments
Returns:
argparse.Namespace: command line arguments test instance
"""
return argparse.Namespace(architecture=None, lock=None, force=False, unsafe=False, report=False,
repository=None, repository_id=None, wait_timeout=-1)
@pytest.fixture
def formatter() -> _HelpFormatter:
"""
fixture for help message formatter
Returns:
_HelpFormatter: help message formatter test instance
"""
return _HelpFormatter("ahriman")
@pytest.fixture
def lock(args: argparse.Namespace, configuration: Configuration) -> Lock:
"""
fixture for file lock
Args:
args(argparse.Namespace): command line arguments fixture
configuration(Configuration): configuration fixture
Returns:
Lock: file lock test instance
"""
_, repository_id = configuration.check_loaded()
return Lock(args, repository_id, configuration)
@pytest.fixture
def parser() -> argparse.ArgumentParser:
"""
fixture for command line arguments parser
Returns:
argparse.ArgumentParser: command line arguments parser test instance
"""
return _parser()
@@ -0,0 +1,211 @@
import argparse
import pytest
from pathlib import Path
from pytest_mock import MockerFixture
from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration
from ahriman.core.exceptions import ExitCode, MissingArchitectureError, MultipleArchitecturesError
from ahriman.models.log_handler import LogHandler
from ahriman.models.repository_id import RepositoryId
def test_call(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must call inside lock
"""
args.configuration = Path("")
args.log_handler = LogHandler.Console
args.quiet = False
args.report = False
mocker.patch("ahriman.application.handlers.handler.Handler.run")
configuration_mock = mocker.patch("ahriman.core.configuration.Configuration.from_path", return_value=configuration)
log_handler_mock = mocker.patch("ahriman.core.log.log_loader.LogLoader.handler", return_value=args.log_handler)
log_load_mock = mocker.patch("ahriman.core.log.log_loader.LogLoader.load")
enter_mock = mocker.patch("ahriman.application.lock.Lock.__enter__")
exit_mock = mocker.patch("ahriman.application.lock.Lock.__exit__")
_, repository_id = configuration.check_loaded()
assert Handler.call(args, repository_id)
configuration_mock.assert_called_once_with(args.configuration, repository_id)
log_handler_mock.assert_called_once_with(args.log_handler)
log_load_mock.assert_called_once_with(
repository_id,
configuration,
args.log_handler,
quiet=args.quiet,
report=args.report)
enter_mock.assert_called_once_with()
exit_mock.assert_called_once_with(None, None, None)
def test_call_exception(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must process exception
"""
args.configuration = Path("")
args.quiet = False
mocker.patch("ahriman.core.configuration.Configuration.from_path", side_effect=Exception)
logging_mock = mocker.patch("logging.Logger.exception")
_, repository_id = configuration.check_loaded()
assert not Handler.call(args, repository_id)
logging_mock.assert_called_once_with(pytest.helpers.anyvar(str, strict=True))
def test_call_exit_code(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must process exitcode exception
"""
args.configuration = Path("")
args.quiet = False
mocker.patch("ahriman.core.configuration.Configuration.from_path", side_effect=ExitCode)
logging_mock = mocker.patch("logging.Logger.exception")
_, repository_id = configuration.check_loaded()
assert not Handler.call(args, repository_id)
logging_mock.assert_not_called()
def test_execute(args: argparse.Namespace, mocker: MockerFixture) -> None:
"""
must run execution in multiple processes
"""
ids = [
RepositoryId("i686", "aur"),
RepositoryId("x86_64", "aur"),
]
mocker.patch("ahriman.application.handlers.handler.Handler.repositories_extract", return_value=ids)
starmap_mock = mocker.patch("multiprocessing.pool.Pool.starmap")
Handler.execute(args)
starmap_mock.assert_called_once_with(Handler.call, [(args, repository_id) for repository_id in ids])
def test_execute_multiple_not_supported(args: argparse.Namespace, mocker: MockerFixture) -> None:
"""
must raise an exception if multiple architectures are not supported by the handler
"""
args.command = "web"
mocker.patch("ahriman.application.handlers.handler.Handler.repositories_extract", return_value=[
RepositoryId("i686", "aur"),
RepositoryId("x86_64", "aur"),
])
mocker.patch.object(Handler, "ALLOW_MULTI_ARCHITECTURE_RUN", False)
with pytest.raises(MultipleArchitecturesError):
Handler.execute(args)
def test_execute_single(args: argparse.Namespace, mocker: MockerFixture) -> None:
"""
must run execution in current process if only one architecture supplied
"""
mocker.patch("ahriman.application.handlers.handler.Handler.repositories_extract", return_value=[
RepositoryId("x86_64", "aur"),
])
starmap_mock = mocker.patch("multiprocessing.pool.Pool.starmap")
Handler.execute(args)
starmap_mock.assert_not_called()
def test_run(args: argparse.Namespace, configuration: Configuration) -> None:
"""
must raise NotImplemented for missing method
"""
_, repository_id = configuration.check_loaded()
with pytest.raises(NotImplementedError):
Handler.run(args, repository_id, configuration, report=True)
def test_check_status() -> None:
"""
must raise exception in case if predicate is True and enabled
"""
Handler.check_status(False, True)
Handler.check_status(False, False)
Handler.check_status(False, lambda: True)
Handler.check_status(False, lambda: False)
Handler.check_status(True, True)
with pytest.raises(ExitCode):
Handler.check_status(True, False)
Handler.check_status(True, lambda: True)
with pytest.raises(ExitCode):
Handler.check_status(True, lambda: False)
def test_repositories_extract(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must generate list of available repositories based on flags
"""
args.architecture = "arch"
args.configuration = configuration.path
args.repository = "repo"
mocker.patch("ahriman.core.configuration.Configuration.load", new=lambda self, _: self.copy_from(configuration))
extract_mock = mocker.patch("ahriman.core.repository.Explorer.repositories_extract",
return_value=[RepositoryId("arch", "repo")])
assert Handler.repositories_extract(args) == [RepositoryId("arch", "repo")]
extract_mock.assert_called_once_with(pytest.helpers.anyvar(Configuration, True), args.repository, args.architecture)
def test_repositories_extract_empty(args: argparse.Namespace, configuration: Configuration,
mocker: MockerFixture) -> None:
"""
must raise exception if no available architectures found
"""
args.command = "config"
args.configuration = configuration.path
mocker.patch("ahriman.core.configuration.Configuration.load", new=lambda self, _: self.copy_from(configuration))
mocker.patch("ahriman.core.repository.Explorer.repositories_extract", return_value=[])
with pytest.raises(MissingArchitectureError):
Handler.repositories_extract(args)
def test_repositories_extract_systemd(args: argparse.Namespace, configuration: Configuration,
mocker: MockerFixture) -> None:
"""
must extract repository list for systemd units
"""
args.configuration = configuration.path
args.repository_id = "i686/some/repo/name"
mocker.patch("ahriman.core.configuration.Configuration.load", new=lambda self, _: self.copy_from(configuration))
extract_mock = mocker.patch("ahriman.core.repository.Explorer.repositories_extract",
return_value=[RepositoryId("i686", "some-repo-name")])
assert Handler.repositories_extract(args) == [RepositoryId("i686", "some-repo-name")]
extract_mock.assert_called_once_with(pytest.helpers.anyvar(Configuration, True), "some-repo-name", "i686")
def test_repositories_extract_systemd_with_dash(args: argparse.Namespace, configuration: Configuration,
mocker: MockerFixture) -> None:
"""
must extract repository list by using dash separated identifier
"""
args.configuration = configuration.path
args.repository_id = "i686-some-repo-name"
mocker.patch("ahriman.core.configuration.Configuration.load", new=lambda self, _: self.copy_from(configuration))
extract_mock = mocker.patch("ahriman.core.repository.Explorer.repositories_extract",
return_value=[RepositoryId("i686", "some-repo-name")])
assert Handler.repositories_extract(args) == [RepositoryId("i686", "some-repo-name")]
extract_mock.assert_called_once_with(pytest.helpers.anyvar(Configuration, True), "some-repo-name", "i686")
def test_repositories_extract_systemd_legacy(args: argparse.Namespace, configuration: Configuration,
mocker: MockerFixture) -> None:
"""
must extract repository list for systemd units in legacy format
"""
args.configuration = configuration.path
args.repository_id = "i686"
mocker.patch("ahriman.core.configuration.Configuration.load", new=lambda self, _: self.copy_from(configuration))
extract_mock = mocker.patch("ahriman.core.repository.Explorer.repositories_extract",
return_value=[RepositoryId("i686", "aur")])
assert Handler.repositories_extract(args) == [RepositoryId("i686", "aur")]
extract_mock.assert_called_once_with(pytest.helpers.anyvar(Configuration, True), None, "i686")
@@ -0,0 +1,85 @@
import argparse
import pytest
from pytest_mock import MockerFixture
from ahriman.application.application import Application
from ahriman.application.handlers.add import Add
from ahriman.core.configuration import Configuration
from ahriman.core.repository import Repository
from ahriman.models.package_source import PackageSource
from ahriman.models.pkgbuild_patch import PkgbuildPatch
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.package = ["ahriman"]
args.now = False
args.refresh = 0
args.source = PackageSource.Auto
args.username = "username"
args.variable = None
return args
def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
on_start_mock = mocker.patch("ahriman.application.application.Application.on_start")
perform_mock = mocker.patch("ahriman.application.handlers.add.Add.perform_action")
_, repository_id = configuration.check_loaded()
Add.run(args, repository_id, configuration, report=False)
on_start_mock.assert_called_once_with()
perform_mock.assert_called_once_with(pytest.helpers.anyvar(int), args)
def test_perform_action(args: argparse.Namespace, application: Application, mocker: MockerFixture) -> None:
"""
must perform add action
"""
args = _default_args(args)
application_mock = mocker.patch("ahriman.application.application.Application.add")
update_mock = mocker.patch("ahriman.application.handlers.update.Update.perform_action")
Add.perform_action(application, args)
application_mock.assert_called_once_with(args.package, args.source, args.username)
update_mock.assert_not_called()
def test_perform_action_with_patches(args: argparse.Namespace, application: Application, mocker: MockerFixture) -> None:
"""
must perform add action and insert temporary patches
"""
args = _default_args(args)
args.variable = ["KEY=VALUE"]
mocker.patch("ahriman.application.application.Application.add")
patches_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_patches_update")
Add.perform_action(application, args)
patches_mock.assert_called_once_with(args.package[0], PkgbuildPatch("KEY", "VALUE"))
def test_perform_action_with_updates(args: argparse.Namespace, application: Application, mocker: MockerFixture) -> None:
"""
must perform add action with updates after
"""
args = _default_args(args)
args.now = True
mocker.patch("ahriman.application.application.Application.add")
update_mock = mocker.patch("ahriman.application.handlers.update.Update.perform_action")
Add.perform_action(application, args)
update_mock.assert_called_once_with(application, args)
@@ -0,0 +1,84 @@
import argparse
import pytest
from pytest_mock import MockerFixture
from ahriman.application.handlers.archives import Archives
from ahriman.core.configuration import Configuration
from ahriman.core.database import SQLite
from ahriman.core.repository import Repository
from ahriman.models.action import Action
from ahriman.models.package import Package
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.action = Action.List
args.exit_code = False
args.info = False
args.package = "package"
return args
def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
application_mock = mocker.patch("ahriman.core.repository.package_info.PackageInfo.package_archives",
return_value=[package_ahriman])
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
_, repository_id = configuration.check_loaded()
Archives.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(args.package)
check_mock.assert_called_once_with(False, True)
print_mock.assert_called_once_with(verbose=False, log_fn=pytest.helpers.anyvar(int), separator=": ")
def test_run_empty_exception(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must raise ExitCode exception on empty archives result
"""
args = _default_args(args)
args.exit_code = True
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.core.repository.package_info.PackageInfo.package_archives", return_value=[])
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
_, repository_id = configuration.check_loaded()
Archives.run(args, repository_id, configuration, report=False)
check_mock.assert_called_once_with(True, False)
def test_imply_with_report(args: argparse.Namespace, configuration: Configuration, database: SQLite,
mocker: MockerFixture) -> None:
"""
must create application object with native reporting
"""
args = _default_args(args)
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
load_mock = mocker.patch("ahriman.core.repository.Repository.load")
_, repository_id = configuration.check_loaded()
Archives.run(args, repository_id, configuration, report=False)
load_mock.assert_called_once_with(repository_id, configuration, database, report=True, refresh_pacman_database=0)
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Archives.ALLOW_MULTI_ARCHITECTURE_RUN
@@ -0,0 +1,63 @@
import argparse
from pathlib import Path
from pytest_mock import MockerFixture
from unittest.mock import MagicMock
from ahriman.application.handlers.backup import Backup
from ahriman.core.configuration import Configuration
from ahriman.models.repository_paths import RepositoryPaths
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.path = Path("result.tar.gz")
return args
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
mocker.patch("ahriman.application.handlers.backup.Backup.get_paths", return_value=[Path("path")])
tarfile = MagicMock()
add_mock = tarfile.__enter__.return_value = MagicMock()
mocker.patch("ahriman.application.handlers.backup.tarfile.open", return_value=tarfile)
_, repository_id = configuration.check_loaded()
Backup.run(args, repository_id, configuration, report=False)
add_mock.add.assert_called_once_with(Path("path"))
def test_get_paths(configuration: Configuration, mocker: MockerFixture) -> None:
"""
must get paths to be archived
"""
# gnupg export mock
mocker.patch("pathlib.Path.is_dir", return_value=True)
mocker.patch.object(RepositoryPaths, "root_owner", (42, 42))
getpwuid_mock = mocker.patch("ahriman.application.handlers.backup.getpwuid", return_value=MagicMock())
# well database does not exist so we override it
database_mock = mocker.patch("ahriman.core.database.SQLite.database_path", return_value=configuration.path)
paths = Backup.get_paths(configuration)
getpwuid_mock.assert_called_once_with(42)
database_mock.assert_called_once_with(configuration)
assert configuration.path in paths
assert all(path.exists() for path in paths if path.name not in (".gnupg", "cache"))
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Backup.ALLOW_MULTI_ARCHITECTURE_RUN
@@ -0,0 +1,98 @@
import argparse
import pytest
from pytest_mock import MockerFixture
from ahriman.application.handlers.change import Change
from ahriman.core.configuration import Configuration
from ahriman.core.database import SQLite
from ahriman.core.repository import Repository
from ahriman.models.action import Action
from ahriman.models.changes import Changes
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.action = Action.List
args.exit_code = False
args.package = "package"
return args
def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
application_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_changes_get",
return_value=Changes("sha", "change"))
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
_, repository_id = configuration.check_loaded()
Change.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(args.package)
check_mock.assert_called_once_with(False, True)
print_mock.assert_called_once_with(verbose=True, log_fn=pytest.helpers.anyvar(int), separator="")
def test_run_empty_exception(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must raise ExitCode exception on empty changes result
"""
args = _default_args(args)
args.exit_code = True
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.core.status.local_client.LocalClient.package_changes_get", return_value=Changes())
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
_, repository_id = configuration.check_loaded()
Change.run(args, repository_id, configuration, report=False)
check_mock.assert_called_once_with(True, False)
def test_run_remove(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must remove package changes
"""
args = _default_args(args)
args.action = Action.Remove
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
update_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_changes_update")
_, repository_id = configuration.check_loaded()
Change.run(args, repository_id, configuration, report=False)
update_mock.assert_called_once_with(args.package, Changes())
def test_imply_with_report(args: argparse.Namespace, configuration: Configuration, database: SQLite,
mocker: MockerFixture) -> None:
"""
must create application object with native reporting
"""
args = _default_args(args)
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
load_mock = mocker.patch("ahriman.core.repository.Repository.load")
_, repository_id = configuration.check_loaded()
Change.run(args, repository_id, configuration, report=False)
load_mock.assert_called_once_with(repository_id, configuration, database, report=True, refresh_pacman_database=0)
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Change.ALLOW_MULTI_ARCHITECTURE_RUN
@@ -0,0 +1,41 @@
import argparse
from pytest_mock import MockerFixture
from ahriman.application.handlers.clean import Clean
from ahriman.core.configuration import Configuration
from ahriman.core.repository import Repository
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.cache = False
args.chroot = False
args.manual = False
args.packages = False
args.pacman = False
return args
def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
application_mock = mocker.patch("ahriman.application.application.Application.clean")
on_start_mock = mocker.patch("ahriman.application.application.Application.on_start")
_, repository_id = configuration.check_loaded()
Clean.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(cache=False, chroot=False, manual=False, packages=False, pacman=False)
on_start_mock.assert_called_once_with()
@@ -0,0 +1,110 @@
import argparse
import pytest
from pytest_mock import MockerFixture
from ahriman.application.application import Application
from ahriman.application.handlers.copy import Copy
from ahriman.core.configuration import Configuration
from ahriman.core.database import SQLite
from ahriman.core.repository import Repository
from ahriman.models.build_status import BuildStatusEnum
from ahriman.models.package import Package
from ahriman.models.package_source import PackageSource
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.source = "source"
args.package = ["ahriman"]
args.exit_code = False
args.remove = False
return args
def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
database: SQLite, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.core.repository.Repository.packages", return_value=[package_ahriman])
application_mock = mocker.patch("ahriman.application.handlers.copy.Copy.copy_package")
update_mock = mocker.patch("ahriman.application.application.Application.update")
remove_mock = mocker.patch("ahriman.application.application.Application.remove")
on_start_mock = mocker.patch("ahriman.application.application.Application.on_start")
_, repository_id = configuration.check_loaded()
Copy.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(package_ahriman, pytest.helpers.anyvar(int), pytest.helpers.anyvar(int))
update_mock.assert_called_once_with([])
remove_mock.assert_not_called()
on_start_mock.assert_called_once_with()
def test_run_remove(args: argparse.Namespace, configuration: Configuration, repository: Repository,
database: SQLite, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must run command and remove packages afterward
"""
args = _default_args(args)
args.remove = True
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.core.repository.Repository.packages", return_value=[package_ahriman])
mocker.patch("ahriman.application.handlers.copy.Copy.copy_package")
mocker.patch("ahriman.application.application.Application.update")
remove_mock = mocker.patch("ahriman.application.application.Application.remove")
_, repository_id = configuration.check_loaded()
Copy.run(args, repository_id, configuration, report=False)
remove_mock.assert_called_once_with(args.package)
def test_run_empty_exception(args: argparse.Namespace, configuration: Configuration, repository: Repository,
database: SQLite, mocker: MockerFixture) -> None:
"""
must raise ExitCode exception on empty result
"""
args = _default_args(args)
args.exit_code = True
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.core.repository.Repository.packages", return_value=[])
mocker.patch("ahriman.application.application.Application.update")
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
_, repository_id = configuration.check_loaded()
Copy.run(args, repository_id, configuration, report=False)
check_mock.assert_called_once_with(True, [])
def test_copy_package(package_ahriman: Package, application: Application, mocker: MockerFixture) -> None:
"""
must copy package between repositories and its metadata
"""
add_mock = mocker.patch("ahriman.application.application.Application.add")
changes_get_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_changes_get")
changes_update_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_changes_update")
deps_get_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_dependencies_get")
deps_update_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_dependencies_update")
package_update_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_update")
path = application.repository.paths.repository / package_ahriman.packages[package_ahriman.base].filename
Copy.copy_package(package_ahriman, application, application)
add_mock.assert_called_once_with([str(path)], PackageSource.Archive)
changes_get_mock.assert_called_once_with(package_ahriman.base)
changes_update_mock.assert_called_once_with(package_ahriman.base, changes_get_mock.return_value)
deps_get_mock.assert_called_once_with(package_ahriman.base)
deps_update_mock.assert_called_once_with(package_ahriman.base, deps_get_mock.return_value)
package_update_mock.assert_called_once_with(package_ahriman, BuildStatusEnum.Pending)
@@ -0,0 +1,78 @@
import argparse
from pytest_mock import MockerFixture
from ahriman.application.handlers.daemon import Daemon
from ahriman.core.configuration import Configuration
from ahriman.core.repository import Repository
from ahriman.models.package import Package
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.interval = 60 * 60 * 12
args.partitions = True
args.refresh = 0
return args
def test_run(args: argparse.Namespace, configuration: Configuration, package_ahriman: Package, repository: Repository,
mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
run_mock = mocker.patch("ahriman.application.handlers.update.Update.run")
iter_mock = mocker.patch("ahriman.application.application.updates_iterator.UpdatesIterator.__iter__",
return_value=iter([[package_ahriman.base]]))
_, repository_id = configuration.check_loaded()
Daemon.run(args, repository_id, configuration, report=True)
args.package = [package_ahriman.base]
run_mock.assert_called_once_with(args, repository_id, configuration, report=True)
iter_mock.assert_called_once_with()
def test_run_no_partitions(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must run command without partitioning
"""
args = _default_args(args)
args.partitions = False
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
run_mock = mocker.patch("ahriman.application.handlers.update.Update.run")
iter_mock = mocker.patch("ahriman.application.application.updates_iterator.UpdatesIterator.__iter__",
return_value=iter([[]]))
_, repository_id = configuration.check_loaded()
Daemon.run(args, repository_id, configuration, report=True)
run_mock.assert_called_once_with(args, repository_id, configuration, report=True)
iter_mock.assert_called_once_with()
def test_run_no_updates(args: argparse.Namespace, configuration: Configuration, package_ahriman: Package,
repository: Repository, mocker: MockerFixture) -> None:
"""
must skip empty update list
"""
args = _default_args(args)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
run_mock = mocker.patch("ahriman.application.handlers.update.Update.run")
iter_mock = mocker.patch("ahriman.application.application.updates_iterator.UpdatesIterator.__iter__",
return_value=iter([[package_ahriman.base], None]))
_, repository_id = configuration.check_loaded()
Daemon.run(args, repository_id, configuration, report=True)
args.package = [package_ahriman.base]
run_mock.assert_called_once_with(args, repository_id, configuration, report=True)
iter_mock.assert_called_once_with()
@@ -0,0 +1,88 @@
import argparse
import pytest
from pytest_mock import MockerFixture
from ahriman.application.handlers.dump import Dump
from ahriman.core.configuration import Configuration
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.info = False
args.key = None
args.section = None
args.secure = True
return args
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
application_mock = mocker.patch("ahriman.core.configuration.Configuration.dump",
return_value=configuration.dump())
_, repository_id = configuration.check_loaded()
Dump.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with()
print_mock.assert_called()
def test_run_info(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must run command with info
"""
args = _default_args(args)
args.info = True
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
_, repository_id = configuration.check_loaded()
Dump.run(args, repository_id, configuration, report=False)
print_mock.assert_called()
def test_run_section(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must run command with filter by section
"""
args = _default_args(args)
args.section = "settings"
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
_, repository_id = configuration.check_loaded()
Dump.run(args, repository_id, configuration, report=False)
print_mock.assert_called_once_with(verbose=False, log_fn=pytest.helpers.anyvar(int), separator=" = ")
def test_run_section_key(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must run command with filter by section and key
"""
args = _default_args(args)
args.section = "settings"
args.key = "include"
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
application_mock = mocker.patch("ahriman.core.configuration.Configuration.dump")
_, repository_id = configuration.check_loaded()
Dump.run(args, repository_id, configuration, report=False)
application_mock.assert_not_called()
print_mock.assert_called_once_with(verbose=False, log_fn=pytest.helpers.anyvar(int), separator=": ")
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Dump.ALLOW_MULTI_ARCHITECTURE_RUN
@@ -0,0 +1,54 @@
import argparse
from pytest_mock import MockerFixture
from ahriman.application.ahriman import _parser
from ahriman.application.handlers.help import Help
from ahriman.core.configuration import Configuration
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.parser = _parser
args.subcommand = None
return args
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
parse_mock = mocker.patch("argparse.ArgumentParser.parse_args")
_, repository_id = configuration.check_loaded()
Help.run(args, repository_id, configuration, report=False)
parse_mock.assert_called_once_with(["--help"])
def test_run_command(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must run command for specific subcommand
"""
args = _default_args(args)
args.subcommand = "aur-search"
parse_mock = mocker.patch("argparse.ArgumentParser.parse_args")
_, repository_id = configuration.check_loaded()
Help.run(args, repository_id, configuration, report=False)
parse_mock.assert_called_once_with(["aur-search", "--help"])
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Help.ALLOW_MULTI_ARCHITECTURE_RUN
@@ -0,0 +1,53 @@
import argparse
import pytest
from pytest_mock import MockerFixture
from ahriman.application.handlers.hold import Hold
from ahriman.core.configuration import Configuration
from ahriman.core.repository import Repository
from ahriman.models.action import Action
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.package = ["ahriman"]
return args
def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
args.action = Action.Update
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
hold_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_hold_update")
_, repository_id = configuration.check_loaded()
Hold.run(args, repository_id, configuration, report=False)
hold_mock.assert_called_once_with("ahriman", enabled=True)
def test_run_remove(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must remove held status
"""
args = _default_args(args)
args.action = Action.Remove
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
hold_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_hold_update")
_, repository_id = configuration.check_loaded()
Hold.run(args, repository_id, configuration, report=False)
hold_mock.assert_called_once_with("ahriman", enabled=False)
@@ -0,0 +1,43 @@
import argparse
from pytest_mock import MockerFixture
from ahriman.application.handlers.key_import import KeyImport
from ahriman.core.configuration import Configuration
from ahriman.core.repository import Repository
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.key = "0xE989490C"
args.key_server = "keyserver.ubuntu.com"
return args
def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
application_mock = mocker.patch("ahriman.core.sign.gpg.GPG.key_import")
_, repository_id = configuration.check_loaded()
KeyImport.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(args.key_server, args.key)
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not KeyImport.ALLOW_MULTI_ARCHITECTURE_RUN
@@ -0,0 +1,232 @@
import argparse
import pytest
import sys
from pathlib import Path
from pytest_mock import MockerFixture
from ahriman.application.application import Application
from ahriman.application.handlers.patch import Patch
from ahriman.core.configuration import Configuration
from ahriman.core.repository import Repository
from ahriman.models.action import Action
from ahriman.models.package import Package
from ahriman.models.pkgbuild_patch import PkgbuildPatch
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.package = "ahriman"
args.exit_code = False
args.remove = False
args.track = ["*.diff", "*.patch"]
args.variable = None
return args
def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
args.action = Action.Update
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
patch_mock = mocker.patch("ahriman.application.handlers.patch.Patch.patch_create_from_diff",
return_value=(args.package, PkgbuildPatch(None, "patch")))
application_mock = mocker.patch("ahriman.application.handlers.patch.Patch.patch_set_create")
_, repository_id = configuration.check_loaded()
Patch.run(args, repository_id, configuration, report=False)
patch_mock.assert_called_once_with(args.package, repository_id.architecture, args.track)
application_mock.assert_called_once_with(pytest.helpers.anyvar(int), args.package, PkgbuildPatch(None, "patch"))
def test_run_function(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must run command with patch function flag
"""
args = _default_args(args)
args.action = Action.Update
args.patch = "patch"
args.variable = "version"
patch = PkgbuildPatch(args.variable, args.patch)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
patch_mock = mocker.patch("ahriman.application.handlers.patch.Patch.patch_create_from_function",
return_value=patch)
application_mock = mocker.patch("ahriman.application.handlers.patch.Patch.patch_set_create")
_, repository_id = configuration.check_loaded()
Patch.run(args, repository_id, configuration, report=False)
patch_mock.assert_called_once_with(args.variable, args.patch)
application_mock.assert_called_once_with(pytest.helpers.anyvar(int), args.package, patch)
def test_run_list(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must run command with list flag
"""
args = _default_args(args)
args.action = Action.List
args.variable = ["version"]
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
application_mock = mocker.patch("ahriman.application.handlers.patch.Patch.patch_set_list")
_, repository_id = configuration.check_loaded()
Patch.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(pytest.helpers.anyvar(int), args.package, ["version"], False)
def test_run_remove(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must run command with remove flag
"""
args = _default_args(args)
args.action = Action.Remove
args.variable = ["version"]
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
application_mock = mocker.patch("ahriman.application.handlers.patch.Patch.patch_set_remove")
_, repository_id = configuration.check_loaded()
Patch.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(pytest.helpers.anyvar(int), args.package, ["version"])
def test_patch_create_from_diff(package_ahriman: Package, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must create patch from directory tree diff
"""
patch = PkgbuildPatch(None, "patch")
path = Path("local")
mocker.patch("pathlib.Path.mkdir")
package_mock = mocker.patch("ahriman.models.package.Package.from_build", return_value=package_ahriman)
sources_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.patch_create", return_value=patch.value)
_, repository_id = configuration.check_loaded()
assert Patch.patch_create_from_diff(path, repository_id.architecture, ["*.diff"]) == (package_ahriman.base, patch)
package_mock.assert_called_once_with(path, repository_id.architecture, None)
sources_mock.assert_called_once_with(path, "*.diff")
def test_patch_create_from_function(mocker: MockerFixture) -> None:
"""
must create function patch from file
"""
patch = PkgbuildPatch("version", "patch")
read_mock = mocker.patch("pathlib.Path.read_text", return_value=patch.value)
assert Patch.patch_create_from_function(patch.key, Path("local")) == patch
read_mock.assert_called_once_with(encoding="utf8")
def test_patch_create_from_function_stdin(mocker: MockerFixture) -> None:
"""
must create function patch from stdin
"""
patch = PkgbuildPatch("version", "This is a patch")
mocker.patch.object(sys, "stdin", patch.value.splitlines())
assert Patch.patch_create_from_function(patch.key, None) == patch
def test_patch_create_from_function_strip(mocker: MockerFixture) -> None:
"""
must remove spaces at the beginning and at the end of the line
"""
patch = PkgbuildPatch("version", "This is a patch")
mocker.patch.object(sys, "stdin", ["\n"] + patch.value.splitlines() + ["\n"])
assert Patch.patch_create_from_function(patch.key, None) == patch
def test_patch_create_from_function_array(mocker: MockerFixture) -> None:
"""
must correctly read array variable
"""
patch = PkgbuildPatch("version", ["array", "patch"])
mocker.patch("pathlib.Path.read_text", return_value=f"({" ".join(patch.value)})")
assert Patch.patch_create_from_function(patch.key, Path("local")) == patch
def test_patch_set_list(application: Application, mocker: MockerFixture) -> None:
"""
must list available patches for the command
"""
get_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_patches_get",
return_value=[PkgbuildPatch(None, "patch"), PkgbuildPatch("version", "value")])
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
Patch.patch_set_list(application, "ahriman", ["version"], False)
get_mock.assert_called_once_with("ahriman", None)
print_mock.assert_called_once_with(verbose=True, log_fn=pytest.helpers.anyvar(int), separator=" = ")
check_mock.assert_called_once_with(False, [PkgbuildPatch(key='version', value='value')])
def test_patch_set_list_all(application: Application, mocker: MockerFixture) -> None:
"""
must list all available patches for the command
"""
get_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_patches_get",
return_value=[PkgbuildPatch(None, "patch")])
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
Patch.patch_set_list(application, "ahriman", None, False)
get_mock.assert_called_once_with("ahriman", None)
print_mock.assert_called_once_with(verbose=True, log_fn=pytest.helpers.anyvar(int), separator=" = ")
check_mock.assert_called_once_with(False, [PkgbuildPatch(key=None, value='patch')])
def test_patch_set_list_empty_exception(application: Application, mocker: MockerFixture) -> None:
"""
must raise ExitCode exception on empty patch list
"""
mocker.patch("ahriman.core.status.local_client.LocalClient.package_patches_get", return_value={})
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
Patch.patch_set_list(application, "ahriman", [], True)
check_mock.assert_called_once_with(True, [])
def test_patch_set_create(application: Application, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must create patch set for the package
"""
create_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_patches_update")
Patch.patch_set_create(application, package_ahriman.base, PkgbuildPatch("version", package_ahriman.version))
create_mock.assert_called_once_with(package_ahriman.base, PkgbuildPatch("version", package_ahriman.version))
def test_patch_set_remove(application: Application, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must remove patch set for the package
"""
remove_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_patches_remove")
Patch.patch_set_remove(application, package_ahriman.base, ["version"])
remove_mock.assert_called_once_with(package_ahriman.base, "version")
def test_patch_set_remove_all(application: Application, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must remove all patches for the package
"""
remove_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_patches_remove")
Patch.patch_set_remove(application, package_ahriman.base, None)
remove_mock.assert_called_once_with(package_ahriman.base, None)
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Patch.ALLOW_MULTI_ARCHITECTURE_RUN
@@ -0,0 +1,100 @@
import argparse
import pytest
from pytest_mock import MockerFixture
from ahriman.application.handlers.pkgbuild import Pkgbuild
from ahriman.core.configuration import Configuration
from ahriman.core.database import SQLite
from ahriman.core.repository import Repository
from ahriman.models.action import Action
from ahriman.models.changes import Changes
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.action = Action.List
args.exit_code = False
args.package = "package"
return args
def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
application_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_changes_get",
return_value=Changes("sha", "change", "pkgbuild content"))
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
_, repository_id = configuration.check_loaded()
Pkgbuild.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(args.package)
check_mock.assert_called_once_with(False, True)
print_mock.assert_called_once_with(verbose=True, log_fn=pytest.helpers.anyvar(int), separator="")
def test_run_empty_exception(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must raise ExitCode exception on empty pkgbuild result
"""
args = _default_args(args)
args.exit_code = True
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.core.status.local_client.LocalClient.package_changes_get", return_value=Changes())
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
_, repository_id = configuration.check_loaded()
Pkgbuild.run(args, repository_id, configuration, report=False)
check_mock.assert_called_once_with(True, False)
def test_run_remove(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must remove package pkgbuild
"""
args = _default_args(args)
args.action = Action.Remove
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
changes = Changes("sha", "change", "pkgbuild content")
mocker.patch("ahriman.core.status.local_client.LocalClient.package_changes_get", return_value=changes)
update_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_changes_update")
_, repository_id = configuration.check_loaded()
Pkgbuild.run(args, repository_id, configuration, report=False)
update_mock.assert_called_once_with(args.package, Changes("sha", "change", None))
def test_imply_with_report(args: argparse.Namespace, configuration: Configuration, database: SQLite,
mocker: MockerFixture) -> None:
"""
must create application object with native reporting
"""
args = _default_args(args)
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
load_mock = mocker.patch("ahriman.core.repository.Repository.load")
_, repository_id = configuration.check_loaded()
Pkgbuild.run(args, repository_id, configuration, report=False)
load_mock.assert_called_once_with(repository_id, configuration, database, report=True, refresh_pacman_database=0)
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Pkgbuild.ALLOW_MULTI_ARCHITECTURE_RUN
@@ -0,0 +1,198 @@
import argparse
import pytest
from pytest_mock import MockerFixture
from unittest.mock import call as MockCall
from ahriman.application.application import Application
from ahriman.application.handlers.rebuild import Rebuild
from ahriman.core.configuration import Configuration
from ahriman.core.repository import Repository
from ahriman.models.build_status import BuildStatus, BuildStatusEnum
from ahriman.models.package import Package
from ahriman.models.packagers import Packagers
from ahriman.models.result import Result
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.depends_on = None
args.dry_run = False
args.from_database = False
args.exit_code = False
args.increment = True
args.status = None
args.username = "username"
return args
def test_run(args: argparse.Namespace, package_ahriman: Package, configuration: Configuration,
repository: Repository, mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
result = Result()
result.add_updated(package_ahriman)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
extract_mock = mocker.patch("ahriman.application.handlers.rebuild.Rebuild.extract_packages",
return_value=[package_ahriman])
application_packages_mock = mocker.patch("ahriman.core.repository.repository.Repository.packages_depend_on",
return_value=[package_ahriman])
application_mock = mocker.patch("ahriman.application.application.Application.update", return_value=result)
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
on_start_mock = mocker.patch("ahriman.application.application.Application.on_start")
_, repository_id = configuration.check_loaded()
Rebuild.run(args, repository_id, configuration, report=False)
extract_mock.assert_called_once_with(pytest.helpers.anyvar(int), args.status, from_database=args.from_database)
application_packages_mock.assert_called_once_with([package_ahriman], None)
application_mock.assert_called_once_with([package_ahriman], Packagers(args.username), bump_pkgrel=args.increment)
check_mock.assert_has_calls([MockCall(False, [package_ahriman]), MockCall(False, True)])
on_start_mock.assert_called_once_with()
def test_run_extract_packages(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must run command from database
"""
args = _default_args(args)
args.from_database = True
args.dry_run = True
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.application.application.Application.add")
mocker.patch("ahriman.application.application.Application.print_updates")
extract_mock = mocker.patch("ahriman.application.handlers.rebuild.Rebuild.extract_packages", return_value=[])
_, repository_id = configuration.check_loaded()
Rebuild.run(args, repository_id, configuration, report=False)
extract_mock.assert_called_once_with(pytest.helpers.anyvar(int), args.status, from_database=args.from_database)
def test_run_dry_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must run command without update itself
"""
args = _default_args(args)
args.dry_run = True
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.application.handlers.rebuild.Rebuild.extract_packages", return_value=[package_ahriman])
application_mock = mocker.patch("ahriman.application.application.Application.update")
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
print_mock = mocker.patch("ahriman.application.application.Application.print_updates")
_, repository_id = configuration.check_loaded()
Rebuild.run(args, repository_id, configuration, report=False)
application_mock.assert_not_called()
check_mock.assert_called_once_with(False, [package_ahriman])
print_mock.assert_called_once_with([package_ahriman], log_fn=pytest.helpers.anyvar(int))
def test_run_filter(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must run command with depends on filter
"""
args = _default_args(args)
args.depends_on = ["python-aur"]
mocker.patch("ahriman.application.application.Application.update")
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.application.handlers.rebuild.Rebuild.extract_packages", return_value=[])
application_packages_mock = mocker.patch("ahriman.core.repository.repository.Repository.packages_depend_on")
_, repository_id = configuration.check_loaded()
Rebuild.run(args, repository_id, configuration, report=False)
application_packages_mock.assert_called_once_with([], ["python-aur"])
def test_run_without_filter(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must run command for all packages if no filter supplied
"""
args = _default_args(args)
mocker.patch("ahriman.application.application.Application.update")
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.application.handlers.rebuild.Rebuild.extract_packages", return_value=[])
application_packages_mock = mocker.patch("ahriman.core.repository.repository.Repository.packages_depend_on")
_, repository_id = configuration.check_loaded()
Rebuild.run(args, repository_id, configuration, report=False)
application_packages_mock.assert_called_once_with([], None)
def test_run_update_empty_exception(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must raise ExitCode exception on empty update list
"""
args = _default_args(args)
args.exit_code = True
args.dry_run = True
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.application.handlers.rebuild.Rebuild.extract_packages")
mocker.patch("ahriman.core.repository.repository.Repository.packages_depend_on", return_value=[])
mocker.patch("ahriman.application.application.Application.print_updates")
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
_, repository_id = configuration.check_loaded()
Rebuild.run(args, repository_id, configuration, report=False)
check_mock.assert_called_once_with(True, [])
def test_run_build_empty_exception(args: argparse.Namespace, configuration: Configuration, repository: Repository,
package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must raise ExitCode exception on empty update result
"""
args = _default_args(args)
args.exit_code = True
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.application.handlers.rebuild.Rebuild.extract_packages")
mocker.patch("ahriman.core.repository.repository.Repository.packages_depend_on", return_value=[package_ahriman])
mocker.patch("ahriman.application.application.Application.update", return_value=Result())
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
_, repository_id = configuration.check_loaded()
Rebuild.run(args, repository_id, configuration, report=False)
check_mock.assert_has_calls([MockCall(True, [package_ahriman]), MockCall(True, False)])
def test_extract_packages(application: Application, mocker: MockerFixture) -> None:
"""
must extract packages from database
"""
packages_mock = mocker.patch("ahriman.core.repository.repository.Repository.packages")
Rebuild.extract_packages(application, None, from_database=False)
packages_mock.assert_called_once_with()
def test_extract_packages_by_status(application: Application, mocker: MockerFixture) -> None:
"""
must extract packages from database and filter them by status
"""
packages_mock = mocker.patch("ahriman.core.database.SQLite.packages_get", return_value=[
("package1", BuildStatus(BuildStatusEnum.Success)),
("package2", BuildStatus(BuildStatusEnum.Failed)),
])
assert Rebuild.extract_packages(application, BuildStatusEnum.Failed, from_database=True) == ["package2"]
packages_mock.assert_called_once_with(application.repository_id)
def test_extract_packages_from_database(application: Application, mocker: MockerFixture) -> None:
"""
must extract packages from database
"""
packages_mock = mocker.patch("ahriman.core.database.SQLite.packages_get")
Rebuild.extract_packages(application, None, from_database=True)
packages_mock.assert_called_once_with(application.repository_id)
@@ -0,0 +1,27 @@
import argparse
from pytest_mock import MockerFixture
from ahriman.application.handlers.reload import Reload
from ahriman.core.configuration import Configuration
from ahriman.core.repository import Repository
def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must run command
"""
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
run_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.configuration_reload")
_, repository_id = configuration.check_loaded()
Reload.run(args, repository_id, configuration, report=False)
run_mock.assert_called_once_with()
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Reload.ALLOW_MULTI_ARCHITECTURE_RUN
@@ -0,0 +1,37 @@
import argparse
from pytest_mock import MockerFixture
from ahriman.application.handlers.remove import Remove
from ahriman.core.configuration import Configuration
from ahriman.core.repository import Repository
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.package = []
return args
def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
application_mock = mocker.patch("ahriman.application.application.Application.remove")
on_start_mock = mocker.patch("ahriman.application.application.Application.on_start")
_, repository_id = configuration.check_loaded()
Remove.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with([])
on_start_mock.assert_called_once_with()
@@ -0,0 +1,62 @@
import argparse
import pytest
from pytest_mock import MockerFixture
from ahriman.application.handlers.remove_unknown import RemoveUnknown
from ahriman.core.configuration import Configuration
from ahriman.core.repository import Repository
from ahriman.models.package import Package
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.dry_run = False
return args
def test_run(args: argparse.Namespace, package_ahriman: Package, configuration: Configuration,
repository: Repository, mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
application_mock = mocker.patch("ahriman.application.application.Application.unknown",
return_value=[package_ahriman])
remove_mock = mocker.patch("ahriman.application.application.Application.remove")
on_start_mock = mocker.patch("ahriman.application.application.Application.on_start")
_, repository_id = configuration.check_loaded()
RemoveUnknown.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with()
remove_mock.assert_called_once_with([package_ahriman])
on_start_mock.assert_called_once_with()
def test_run_dry_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must run simplified command
"""
args = _default_args(args)
args.dry_run = True
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
application_mock = mocker.patch("ahriman.application.application.Application.unknown",
return_value=[package_ahriman])
remove_mock = mocker.patch("ahriman.application.application.Application.remove")
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
_, repository_id = configuration.check_loaded()
RemoveUnknown.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with()
remove_mock.assert_not_called()
print_mock.assert_called_once_with(verbose=False, log_fn=pytest.helpers.anyvar(int), separator=": ")
@@ -0,0 +1,37 @@
import argparse
import pytest
from pytest_mock import MockerFixture
from ahriman.application.handlers.repositories import Repositories
from ahriman.core.configuration import Configuration
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.configuration = None # doesn't matter actually
args.id_only = False
return args
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
_, repository_id = configuration.check_loaded()
application_mock = mocker.patch("ahriman.application.handlers.handler.Handler.repositories_extract",
return_value=[repository_id])
Repositories.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(pytest.helpers.anyvar(int))
print_mock.assert_called_once_with(verbose=not args.id_only, log_fn=pytest.helpers.anyvar(int), separator=": ")
@@ -0,0 +1,44 @@
import argparse
from pathlib import Path
from pytest_mock import MockerFixture
from unittest.mock import MagicMock
from ahriman.application.handlers.restore import Restore
from ahriman.core.configuration import Configuration
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.path = Path("result.tar.gz")
args.output = Path.cwd()
return args
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
tarfile = MagicMock()
extract_mock = tarfile.__enter__.return_value = MagicMock()
mocker.patch("ahriman.application.handlers.restore.tarfile.open", return_value=tarfile)
_, repository_id = configuration.check_loaded()
Restore.run(args, repository_id, configuration, report=False)
extract_mock.extractall.assert_called_once_with(path=args.output, filter="data")
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Restore.ALLOW_MULTI_ARCHITECTURE_RUN
@@ -0,0 +1,113 @@
import argparse
import pytest
from pytest_mock import MockerFixture
from ahriman.application.application import Application
from ahriman.application.handlers.rollback import Rollback
from ahriman.core.configuration import Configuration
from ahriman.core.exceptions import UnknownPackageError
from ahriman.core.repository import Repository
from ahriman.models.package import Package
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.package = "ahriman"
args.version = "1.0.0-1"
args.hold = False
return args
def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository, package_ahriman: Package,
mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
artifacts = [package.filepath for package in package_ahriman.packages.values()]
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
on_start_mock = mocker.patch("ahriman.application.application.Application.on_start")
load_mock = mocker.patch("ahriman.application.handlers.rollback.Rollback.package_load",
return_value=package_ahriman)
artifacts_mock = mocker.patch("ahriman.application.handlers.rollback.Rollback.package_artifacts",
return_value=artifacts)
perform_mock = mocker.patch("ahriman.application.handlers.add.Add.perform_action")
hold_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_hold_update")
_, repository_id = configuration.check_loaded()
Rollback.run(args, repository_id, configuration, report=False)
on_start_mock.assert_called_once_with()
load_mock.assert_called_once_with(pytest.helpers.anyvar(int), package_ahriman.base, args.version)
artifacts_mock.assert_called_once_with(pytest.helpers.anyvar(int), package_ahriman)
perform_mock.assert_called_once_with(pytest.helpers.anyvar(int), args)
hold_mock.assert_not_called()
def test_run_hold(args: argparse.Namespace, configuration: Configuration, repository: Repository,
package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must hold package after rollback
"""
args = _default_args(args)
args.hold = True
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.application.application.Application.on_start")
mocker.patch("ahriman.application.handlers.rollback.Rollback.package_load", return_value=package_ahriman)
mocker.patch("ahriman.application.handlers.rollback.Rollback.package_artifacts", return_value=[])
mocker.patch("ahriman.application.handlers.add.Add.perform_action")
hold_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_hold_update")
_, repository_id = configuration.check_loaded()
Rollback.run(args, repository_id, configuration, report=False)
hold_mock.assert_called_once_with(package_ahriman.base, enabled=True)
def test_package_artifacts(application: Application, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must return package artifacts
"""
artifacts = [package.filepath for package in package_ahriman.packages.values()]
lookup_mock = mocker.patch("ahriman.core.repository.Repository.package_archives_lookup", return_value=artifacts)
assert Rollback.package_artifacts(application, package_ahriman) == artifacts
lookup_mock.assert_called_once_with(package_ahriman)
def test_package_artifacts_empty(application: Application, package_ahriman: Package,
mocker: MockerFixture) -> None:
"""
must raise UnknownPackageError if no artifacts found
"""
mocker.patch("ahriman.core.repository.Repository.package_archives_lookup", return_value=[])
with pytest.raises(UnknownPackageError):
Rollback.package_artifacts(application, package_ahriman)
def test_package_load(application: Application, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must load package from reporter
"""
package_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_get",
return_value=[(package_ahriman, None)])
result = Rollback.package_load(application, package_ahriman.base, "2.0.0-1")
assert result.version == "2.0.0-1"
package_mock.assert_called_once_with(package_ahriman.base)
def test_package_load_unknown(application: Application, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must raise UnknownPackageError if package not found
"""
mocker.patch("ahriman.core.status.local_client.LocalClient.package_get", return_value=[])
with pytest.raises(UnknownPackageError):
Rollback.package_load(application, package_ahriman.base, package_ahriman.version)
@@ -0,0 +1,71 @@
import argparse
import pytest
from pytest_mock import MockerFixture
from ahriman.application.ahriman import _parser
from ahriman.application.handlers.run import Run
from ahriman.core.configuration import Configuration
from ahriman.core.exceptions import ExitCode
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.command = ["help"]
args.parser = _parser
return args
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
application_mock = mocker.patch("ahriman.application.handlers.run.Run.run_command")
_, repository_id = configuration.check_loaded()
Run.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(["help"], pytest.helpers.anyvar(int))
def test_run_failed(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must run commands until success
"""
args = _default_args(args)
args.command = ["help", "config"]
application_mock = mocker.patch("ahriman.application.handlers.run.Run.run_command", return_value=False)
_, repository_id = configuration.check_loaded()
with pytest.raises(ExitCode):
Run.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(["help"], pytest.helpers.anyvar(int))
def test_run_command(mocker: MockerFixture) -> None:
"""
must correctly run external command
"""
# because of dynamic load we need to patch exact instance of the object
parser = _parser()
subparser = next((action for action in parser._actions if isinstance(action, argparse._SubParsersAction)), None)
action = subparser.choices["help"]
execute_mock = mocker.patch.object(action.get_default("handler"), "execute")
Run.run_command(["help"], parser)
execute_mock.assert_called_once_with(pytest.helpers.anyvar(int))
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Run.ALLOW_MULTI_ARCHITECTURE_RUN
@@ -0,0 +1,147 @@
import argparse
import dataclasses
import pytest
from pytest_mock import MockerFixture
from unittest.mock import call as MockCall
from ahriman.application.handlers.search import Search
from ahriman.core.configuration import Configuration
from ahriman.core.exceptions import OptionError
from ahriman.core.repository import Repository
from ahriman.models.aur_package import AURPackage
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.search = ["ahriman"]
args.exit_code = False
args.info = False
args.sort_by = "name"
return args
def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
aur_package_ahriman: AURPackage, mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
aur_search_mock = mocker.patch("ahriman.core.alpm.remote.AUR.multisearch", return_value=[aur_package_ahriman])
official_search_mock = mocker.patch("ahriman.core.alpm.remote.Official.multisearch",
return_value=[aur_package_ahriman])
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
_, repository_id = configuration.check_loaded()
Search.run(args, repository_id, configuration, report=False)
aur_search_mock.assert_called_once_with("ahriman")
official_search_mock.assert_called_once_with("ahriman")
check_mock.assert_called_once_with(False, True)
print_mock.assert_has_calls([
MockCall(verbose=False, log_fn=pytest.helpers.anyvar(int), separator=": "),
MockCall(verbose=False, log_fn=pytest.helpers.anyvar(int), separator=": "),
])
def test_run_empty_exception(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must raise ExitCode exception on empty result list
"""
args = _default_args(args)
args.exit_code = True
mocker.patch("ahriman.core.alpm.remote.AUR.multisearch", return_value=[])
mocker.patch("ahriman.core.alpm.remote.Official.multisearch", return_value=[])
mocker.patch("ahriman.core.formatters.Printer.print")
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
_, repository_id = configuration.check_loaded()
Search.run(args, repository_id, configuration, report=False)
check_mock.assert_called_once_with(True, False)
def test_run_sort(args: argparse.Namespace, configuration: Configuration, repository: Repository,
aur_package_ahriman: AURPackage, mocker: MockerFixture) -> None:
"""
must run command with sorting
"""
args = _default_args(args)
mocker.patch("ahriman.core.alpm.remote.AUR.multisearch", return_value=[aur_package_ahriman])
mocker.patch("ahriman.core.alpm.remote.Official.multisearch", return_value=[])
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
sort_mock = mocker.patch("ahriman.application.handlers.search.Search.sort")
_, repository_id = configuration.check_loaded()
Search.run(args, repository_id, configuration, report=False)
sort_mock.assert_has_calls([
MockCall([], "name"), MockCall().__iter__(),
MockCall([aur_package_ahriman], "name"), MockCall().__iter__()
])
def test_run_sort_by(args: argparse.Namespace, configuration: Configuration, repository: Repository,
aur_package_ahriman: AURPackage, mocker: MockerFixture) -> None:
"""
must run command with sorting by specified field
"""
args = _default_args(args)
args.sort_by = "field"
mocker.patch("ahriman.core.alpm.remote.AUR.multisearch", return_value=[aur_package_ahriman])
mocker.patch("ahriman.core.alpm.remote.Official.multisearch", return_value=[])
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
sort_mock = mocker.patch("ahriman.application.handlers.search.Search.sort")
_, repository_id = configuration.check_loaded()
Search.run(args, repository_id, configuration, report=False)
sort_mock.assert_has_calls([
MockCall([], "field"), MockCall().__iter__(),
MockCall([aur_package_ahriman], "field"), MockCall().__iter__()
])
def test_sort(aur_package_ahriman: AURPackage) -> None:
"""
must sort package list
"""
another = dataclasses.replace(aur_package_ahriman, name="1", package_base="base")
# sort by name
assert Search.sort([aur_package_ahriman, another], "name") == [another, aur_package_ahriman]
# sort by another field
assert Search.sort([aur_package_ahriman, another], "package_base") == [aur_package_ahriman, another]
# sort by field with the same values
assert Search.sort([aur_package_ahriman, another], "version") == [another, aur_package_ahriman]
def test_sort_exception(aur_package_ahriman: AURPackage) -> None:
"""
must raise an exception on unknown sorting field
"""
with pytest.raises(OptionError):
Search.sort([aur_package_ahriman], "random_field")
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Search.ALLOW_MULTI_ARCHITECTURE_RUN
def test_sort_fields(aur_package_ahriman: AURPackage) -> None:
"""
must store valid field list which are allowed to be used for sorting
"""
expected = {field.name for field in dataclasses.fields(AURPackage)}
assert all(field in expected for field in Search.SORT_FIELDS)
assert all(not isinstance(getattr(aur_package_ahriman, field), list) for field in Search.SORT_FIELDS)
@@ -0,0 +1,68 @@
import argparse
import pytest
from pytest_mock import MockerFixture
from ahriman import __version__
from ahriman.application.handlers.service_updates import ServiceUpdates
from ahriman.core.configuration import Configuration
from ahriman.core.repository import Repository
from ahriman.models.package import Package
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.exit_code = False
return args
def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must run command
"""
package_ahriman.version = "0.0.0-1"
args = _default_args(args)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
package_mock = mocker.patch("ahriman.models.package.Package.from_aur", return_value=package_ahriman)
application_mock = mocker.patch("ahriman.core.formatters.Printer.print")
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
_, repository_id = configuration.check_loaded()
ServiceUpdates.run(args, repository_id, configuration, report=False)
package_mock.assert_called_once_with(package_ahriman.base, None)
application_mock.assert_called_once_with(verbose=True, log_fn=pytest.helpers.anyvar(int), separator=" -> ")
check_mock.assert_called_once_with(args.exit_code, False)
def test_run_skip(args: argparse.Namespace, configuration: Configuration, repository: Repository,
package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must do not perform any actions if package is up-to-date
"""
package_ahriman.version = f"{__version__}-1"
args = _default_args(args)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.models.package.Package.from_aur", return_value=package_ahriman)
application_mock = mocker.patch("ahriman.core.formatters.Printer.print")
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
_, repository_id = configuration.check_loaded()
ServiceUpdates.run(args, repository_id, configuration, report=False)
application_mock.assert_not_called()
check_mock.assert_not_called()
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not ServiceUpdates.ALLOW_MULTI_ARCHITECTURE_RUN
@@ -0,0 +1,286 @@
import argparse
import pytest
from pathlib import Path
from pytest_mock import MockerFixture
from typing import Any
from unittest.mock import call as MockCall
from urllib.parse import quote_plus as url_encode
from ahriman.application.handlers.setup import Setup
from ahriman.core.configuration import Configuration
from ahriman.core.database import SQLite
from ahriman.core.exceptions import MissingArchitectureError
from ahriman.core.repository import Repository
from ahriman.models.repository_id import RepositoryId
from ahriman.models.repository_paths import RepositoryPaths
from ahriman.models.sign_settings import SignSettings
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.architecture = "x86_64"
args.build_as_user = "ahriman"
args.from_configuration = Path("/usr/share/devtools/pacman.conf.d/extra.conf")
args.generate_salt = True
args.makeflags_jobs = True
args.mirror = "mirror"
args.multilib = True
args.packager = "ahriman bot <ahriman@example.com>"
args.repository = "aur"
args.server = None
args.sign_key = "key"
args.sign_target = [SignSettings.Packages]
args.web_port = 8080
args.web_unix_socket = Path("/var/lib/ahriman/ahriman-web.sock")
return args
def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
database: SQLite, repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
ahriman_configuration_mock = mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_ahriman")
devtools_configuration_mock = mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_devtools")
makepkg_configuration_mock = mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_makepkg")
sudo_configuration_mock = mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_sudo")
executable_mock = mocker.patch("ahriman.application.handlers.setup.Setup.executable_create")
init_mock = mocker.patch("ahriman.core.alpm.repo.Repo.init")
owner_guard_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.preserve_owner")
_, repository_id = configuration.check_loaded()
Setup.run(args, repository_id, configuration, report=False)
owner_guard_mock.assert_called_once_with()
ahriman_configuration_mock.assert_called_once_with(args, repository_id, configuration)
devtools_configuration_mock.assert_called_once_with(
repository_id, args.from_configuration, args.mirror, args.multilib, f"file://{repository_paths.repository}")
makepkg_configuration_mock.assert_called_once_with(args.packager, args.makeflags_jobs, repository_paths)
sudo_configuration_mock.assert_called_once_with(repository_paths, repository_id)
executable_mock.assert_called_once_with(repository_paths, repository_id)
init_mock.assert_called_once_with()
def test_run_no_architecture_or_repository(configuration: Configuration) -> None:
"""
must raise MissingArchitectureError if either architecture or repository are not supplied
"""
_, repository_id = configuration.check_loaded()
args = argparse.Namespace(architecture=None, command="service-setup", repository=None)
with pytest.raises(MissingArchitectureError):
Setup.run(args, repository_id, configuration, report=False)
args = argparse.Namespace(architecture=[repository_id.architecture], command="service-setup", repository=None)
with pytest.raises(MissingArchitectureError):
Setup.run(args, repository_id, configuration, report=False)
args = argparse.Namespace(architecture=None, command="service-setup", repository=[repository_id.name])
with pytest.raises(MissingArchitectureError):
Setup.run(args, repository_id, configuration, report=False)
def test_run_with_server(args: argparse.Namespace, configuration: Configuration, repository: Repository,
database: SQLite, mocker: MockerFixture) -> None:
"""
must run command with server specified
"""
args = _default_args(args)
args.server = "server"
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_ahriman")
mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_makepkg")
mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_sudo")
mocker.patch("ahriman.application.handlers.setup.Setup.executable_create")
mocker.patch("ahriman.core.alpm.repo.Repo.init")
devtools_configuration_mock = mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_devtools")
_, repository_id = configuration.check_loaded()
Setup.run(args, repository_id, configuration, report=False)
devtools_configuration_mock.assert_called_once_with(
repository_id, args.from_configuration, args.mirror, args.multilib, "server")
def test_build_command(repository_id: RepositoryId) -> None:
"""
must generate correct build command name
"""
path = Path("local")
build_command = Setup.build_command(path, repository_id)
assert build_command.name == f"{repository_id.name}-{repository_id.architecture}-build"
assert build_command.parent == path
def test_configuration_create_ahriman(args: argparse.Namespace, configuration: Configuration,
repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
"""
must create configuration for the service
"""
args = _default_args(args)
mocker.patch("pathlib.Path.open")
set_option_mock = mocker.patch("ahriman.core.configuration.Configuration.set_option")
write_mock = mocker.patch("ahriman.core.configuration.Configuration.write")
remove_mock = mocker.patch("pathlib.Path.unlink", autospec=True)
_, repository_id = configuration.check_loaded()
command = Setup.build_command(repository_paths.root, repository_id)
Setup.configuration_create_ahriman(args, repository_id, configuration)
set_option_mock.assert_has_calls([
MockCall(Configuration.section_name("build", repository_id.name, repository_id.architecture), "build_command",
str(command)),
MockCall("repository", "name", repository_id.name),
MockCall(Configuration.section_name("build", repository_id.name, repository_id.architecture),
"makechrootpkg_flags", f"-U {args.build_as_user}"),
MockCall(Configuration.section_name(
"alpm", repository_id.name, repository_id.architecture), "mirror", args.mirror),
MockCall(Configuration.section_name("sign", repository_id.name, repository_id.architecture), "target",
" ".join([target.name.lower() for target in args.sign_target])),
MockCall(Configuration.section_name("sign", repository_id.name, repository_id.architecture), "key",
args.sign_key),
MockCall("web", "port", str(args.web_port)),
MockCall("status", "address", f"http://127.0.0.1:{str(args.web_port)}"),
MockCall("web", "unix_socket", str(args.web_unix_socket)),
MockCall("status", "address", f"http+unix://{url_encode(str(args.web_unix_socket))}"),
MockCall("auth", "salt", pytest.helpers.anyvar(str, strict=True)),
])
write_mock.assert_called_once_with(pytest.helpers.anyvar(int))
remove_mock.assert_called_once_with(configuration.include / "00-setup-overrides.ini", missing_ok=True)
def test_configuration_create_ahriman_no_multilib(args: argparse.Namespace, configuration: Configuration,
mocker: MockerFixture) -> None:
"""
must create configuration for the service without multilib repository
"""
args = _default_args(args)
args.multilib = False
mocker.patch("pathlib.Path.open")
mocker.patch("ahriman.core.configuration.Configuration.write")
set_option_mock = mocker.patch("ahriman.core.configuration.Configuration.set_option")
_, repository_id = configuration.check_loaded()
Setup.configuration_create_ahriman(args, repository_id, configuration)
set_option_mock.assert_has_calls([
MockCall(Configuration.section_name("alpm", repository_id.name, repository_id.architecture), "mirror",
args.mirror),
]) # non-strict check called intentionally
def test_configuration_create_devtools(args: argparse.Namespace, configuration: Configuration,
mocker: MockerFixture) -> None:
"""
must create configuration for the devtools
"""
args = _default_args(args)
mocker.patch("pathlib.Path.open")
mocker.patch("ahriman.core.configuration.Configuration.set")
add_section_mock = mocker.patch("ahriman.core.configuration.Configuration.add_section")
write_mock = mocker.patch("ahriman.core.configuration.Configuration.write")
_, repository_id = configuration.check_loaded()
Setup.configuration_create_devtools(repository_id, args.from_configuration, None, args.multilib, "server")
add_section_mock.assert_has_calls([MockCall("multilib"), MockCall(repository_id.name)])
write_mock.assert_called_once_with(pytest.helpers.anyvar(int))
def test_configuration_create_devtools_mirror(args: argparse.Namespace, configuration: Configuration,
mocker: MockerFixture) -> None:
"""
must create configuration for the devtools with mirror set explicitly
"""
def get(section: str, key: str, **kwargs: Any) -> Any:
if section == "core" and key == "Include":
return str(Setup.MIRRORLIST_PATH)
return kwargs["fallback"]
args = _default_args(args)
mocker.patch("pathlib.Path.open")
mocker.patch("ahriman.core.configuration.Configuration.set")
mocker.patch("ahriman.core.configuration.Configuration.write")
mocker.patch("ahriman.core.configuration.Configuration.sections", return_value=["core", "extra"])
get_mock = mocker.patch("ahriman.core.configuration.Configuration.get", side_effect=get)
remove_option_mock = mocker.patch("ahriman.core.configuration.Configuration.remove_option")
set_option_mock = mocker.patch("ahriman.core.configuration.Configuration.set_option")
_, repository_id = configuration.check_loaded()
Setup.configuration_create_devtools(repository_id, args.from_configuration, args.mirror, args.multilib, "server")
get_mock.assert_has_calls([MockCall("core", "Include", fallback=None), MockCall("extra", "Include", fallback=None)])
remove_option_mock.assert_called_once_with("core", "Include")
set_option_mock.assert_has_calls([MockCall("core", "Server", args.mirror)]) # non-strict check called intentionally
def test_configuration_create_devtools_no_multilib(args: argparse.Namespace, configuration: Configuration,
mocker: MockerFixture) -> None:
"""
must create configuration for the devtools without multilib
"""
args = _default_args(args)
mocker.patch("pathlib.Path.open")
mocker.patch("ahriman.core.configuration.Configuration.set")
write_mock = mocker.patch("ahriman.core.configuration.Configuration.write")
_, repository_id = configuration.check_loaded()
Setup.configuration_create_devtools(repository_id, args.from_configuration, args.mirror, False, "server")
write_mock.assert_called_once_with(pytest.helpers.anyvar(int))
def test_configuration_create_makepkg(args: argparse.Namespace, repository_paths: RepositoryPaths,
passwd: Any, mocker: MockerFixture) -> None:
"""
must create makepkg configuration
"""
args = _default_args(args)
mocker.patch("ahriman.application.handlers.setup.getpwuid", return_value=passwd)
write_text_mock = mocker.patch("pathlib.Path.write_text", autospec=True)
Setup.configuration_create_makepkg(args.packager, args.makeflags_jobs, repository_paths)
write_text_mock.assert_called_once_with(
Path("home") / ".makepkg.conf", pytest.helpers.anyvar(str, True), encoding="utf8")
def test_configuration_create_sudo(configuration: Configuration, repository_paths: RepositoryPaths,
mocker: MockerFixture) -> None:
"""
must create sudo configuration
"""
chmod_text_mock = mocker.patch("pathlib.Path.chmod")
write_text_mock = mocker.patch("pathlib.Path.write_text")
_, repository_id = configuration.check_loaded()
Setup.configuration_create_sudo(repository_paths, repository_id)
chmod_text_mock.assert_called_once_with(0o400)
write_text_mock.assert_called_once_with(pytest.helpers.anyvar(str, True), encoding="utf8")
def test_executable_create(configuration: Configuration, repository_paths: RepositoryPaths,
mocker: MockerFixture) -> None:
"""
must create executable
"""
symlink_mock = mocker.patch("pathlib.Path.symlink_to")
unlink_mock = mocker.patch("pathlib.Path.unlink")
_, repository_id = configuration.check_loaded()
Setup.executable_create(repository_paths, repository_id)
symlink_mock.assert_called_once_with(Setup.ARCHBUILD_COMMAND_PATH)
unlink_mock.assert_called_once_with(missing_ok=True)
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Setup.ALLOW_MULTI_ARCHITECTURE_RUN
@@ -0,0 +1,78 @@
import argparse
import pytest
from pytest_mock import MockerFixture
from ahriman.application.handlers.shell import Shell
from ahriman.core.configuration import Configuration
from ahriman.core.repository import Repository
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.code = None
args.verbose = False
return args
def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
application_mock = mocker.patch("ahriman.application.interactive_shell.InteractiveShell.interact")
_, repository_id = configuration.check_loaded()
Shell.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with()
def test_run_eval(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must run command via eval
"""
args = _default_args(args)
args.code = """print("hello world")"""
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
application_mock = mocker.patch("ahriman.application.interactive_shell.InteractiveShell.runcode")
_, repository_id = configuration.check_loaded()
Shell.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(args.code)
def test_run_verbose(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must run command with verbose option
"""
args = _default_args(args)
args.verbose = True
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
read_mock = mocker.patch("pathlib.Path.read_text", return_value="")
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
application_mock = mocker.patch("ahriman.application.interactive_shell.InteractiveShell.interact")
_, repository_id = configuration.check_loaded()
Shell.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with()
read_mock.assert_called_once_with(encoding="utf8")
print_mock.assert_called_once_with(verbose=False, log_fn=pytest.helpers.anyvar(int), separator=": ")
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Shell.ALLOW_MULTI_ARCHITECTURE_RUN
@@ -0,0 +1,35 @@
import argparse
from pytest_mock import MockerFixture
from ahriman.application.handlers.sign import Sign
from ahriman.core.configuration import Configuration
from ahriman.core.repository import Repository
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.package = []
return args
def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
application_mock = mocker.patch("ahriman.application.application.Application.sign")
_, repository_id = configuration.check_loaded()
Sign.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with([])
@@ -0,0 +1,203 @@
import argparse
import pytest
from pathlib import Path
from pytest_mock import MockerFixture
from unittest.mock import call as MockCall
from ahriman.application.handlers.statistics import Statistics
from ahriman.core.configuration import Configuration
from ahriman.core.repository import Repository
from ahriman.core.utils import pretty_datetime, utcnow
from ahriman.models.event import Event, EventType
from ahriman.models.package import Package
from ahriman.models.repository_stats import RepositoryStats
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.chart = None
args.event = EventType.PackageUpdated
args.from_date = None
args.limit = -1
args.offset = 0
args.package = None
args.to_date = None
return args
def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
events = [Event("1", "1"), Event("2", "2")]
stats = RepositoryStats(bases=1, packages=2, archive_size=3, installed_size=4)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
events_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.event_get", return_value=events)
stats_mock = mocker.patch("ahriman.core.status.client.Client.statistics", return_value=stats)
application_mock = mocker.patch("ahriman.application.handlers.statistics.Statistics.stats_per_package")
_, repository_id = configuration.check_loaded()
Statistics.run(args, repository_id, configuration, report=False)
events_mock.assert_called_once_with(args.event, args.package, None, None, args.limit, args.offset)
stats_mock.assert_called_once_with()
application_mock.assert_called_once_with(args.event, events, args.chart)
def test_run_for_package(args: argparse.Namespace, configuration: Configuration, repository: Repository,
package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must run command for specific package
"""
args = _default_args(args)
args.package = package_ahriman.base
events = [Event("1", "1"), Event("2", "2")]
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
events_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.event_get", return_value=events)
application_mock = mocker.patch("ahriman.application.handlers.statistics.Statistics.stats_for_package")
_, repository_id = configuration.check_loaded()
Statistics.run(args, repository_id, configuration, report=False)
events_mock.assert_called_once_with(args.event, args.package, None, None, args.limit, args.offset)
application_mock.assert_called_once_with(args.event, events, args.chart)
def test_run_convert_from_date(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must convert from date
"""
args = _default_args(args)
date = utcnow()
args.from_date = date.isoformat()
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.application.handlers.statistics.Statistics.stats_per_package")
events_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.event_get", return_value=[])
_, repository_id = configuration.check_loaded()
Statistics.run(args, repository_id, configuration, report=False)
events_mock.assert_called_once_with(args.event, args.package, date.timestamp(), None, args.limit, args.offset)
def test_run_convert_to_date(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must convert to date
"""
args = _default_args(args)
date = utcnow()
args.to_date = date.isoformat()
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.application.handlers.statistics.Statistics.stats_per_package")
events_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.event_get", return_value=[])
_, repository_id = configuration.check_loaded()
Statistics.run(args, repository_id, configuration, report=False)
events_mock.assert_called_once_with(args.event, args.package, None, date.timestamp(), args.limit, args.offset)
def test_event_stats(mocker: MockerFixture) -> None:
"""
must print event stats
"""
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
events = [Event("event", "1"), Event("event", "2", took=42.0)]
Statistics.event_stats("event", events)
print_mock.assert_called_once_with(verbose=True, log_fn=pytest.helpers.anyvar(int), separator=": ")
def test_plot_packages(mocker: MockerFixture) -> None:
"""
must plot chart for packages
"""
plot_mock = mocker.patch("matplotlib.pyplot.bar")
save_mock = mocker.patch("matplotlib.pyplot.savefig")
local = Path("local")
Statistics.plot_packages("event", {"1": 1, "2": 2}, local)
plot_mock.assert_called_once_with(["1", "2"], [1, 2])
save_mock.assert_called_once_with(local)
def test_plot_times(mocker: MockerFixture) -> None:
"""
must plot chart for durations
"""
plot_mock = mocker.patch("matplotlib.pyplot.plot")
save_mock = mocker.patch("matplotlib.pyplot.savefig")
local = Path("local")
Statistics.plot_times("event", [
Event("", "", created=1, took=2),
Event("", "", created=3, took=4),
], local)
plot_mock.assert_called_once_with((pretty_datetime(1), pretty_datetime(3)), (2, 4))
save_mock.assert_called_once_with(local)
def test_stats_for_package(mocker: MockerFixture) -> None:
"""
must print statistics for the package
"""
events = [Event("event", "1"), Event("event", "1")]
events_mock = mocker.patch("ahriman.application.handlers.statistics.Statistics.event_stats")
chart_plot = mocker.patch("ahriman.application.handlers.statistics.Statistics.plot_times")
Statistics.stats_for_package("event", events, None)
events_mock.assert_called_once_with("event", events)
chart_plot.assert_not_called()
def test_stats_for_package_with_chart(mocker: MockerFixture) -> None:
"""
must generate chart for package stats
"""
local = Path("local")
events = [Event("event", "1"), Event("event", "1")]
mocker.patch("ahriman.application.handlers.statistics.Statistics.event_stats")
chart_plot = mocker.patch("ahriman.application.handlers.statistics.Statistics.plot_times")
Statistics.stats_for_package("event", events, local)
chart_plot.assert_called_once_with("event", events, local)
def test_stats_per_package(mocker: MockerFixture) -> None:
"""
must print statistics per package
"""
events = [Event("event", "1"), Event("event", "2"), Event("event", "1")]
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
events_mock = mocker.patch("ahriman.application.handlers.statistics.Statistics.event_stats")
chart_plot = mocker.patch("ahriman.application.handlers.statistics.Statistics.plot_packages")
Statistics.stats_per_package("event", events, None)
print_mock.assert_has_calls([
MockCall(verbose=True, log_fn=pytest.helpers.anyvar(int), separator=": "),
MockCall(verbose=True, log_fn=pytest.helpers.anyvar(int), separator=": "),
])
events_mock.assert_called_once_with("event", events)
chart_plot.assert_not_called()
def test_stats_per_package_with_chart(mocker: MockerFixture) -> None:
"""
must print statistics per package with chart
"""
local = Path("local")
events = [Event("event", "1"), Event("event", "2"), Event("event", "1")]
mocker.patch("ahriman.application.handlers.statistics.Statistics.event_stats")
chart_plot = mocker.patch("ahriman.application.handlers.statistics.Statistics.plot_packages")
Statistics.stats_per_package("event", events, local)
chart_plot.assert_called_once_with("event", {"1": 2, "2": 1}, local)
@@ -0,0 +1,152 @@
import argparse
import pytest
from pytest_mock import MockerFixture
from unittest.mock import call as MockCall
from ahriman.application.handlers.status import Status
from ahriman.core.configuration import Configuration
from ahriman.core.database import SQLite
from ahriman.core.repository import Repository
from ahriman.models.build_status import BuildStatus, BuildStatusEnum
from ahriman.models.package import Package
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.ahriman = True
args.exit_code = False
args.info = False
args.package = []
args.status = None
return args
def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
package_ahriman: Package, package_python_schedule: Package, mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
packages = [
(package_ahriman, BuildStatus(BuildStatusEnum.Success)),
(package_python_schedule, BuildStatus(BuildStatusEnum.Failed)),
]
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
application_mock = mocker.patch("ahriman.core.status.Client.status_get")
packages_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_get", return_value=packages)
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
_, repository_id = configuration.check_loaded()
Status.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with()
packages_mock.assert_called_once_with(None)
check_mock.assert_called_once_with(False, packages)
print_mock.assert_has_calls([
MockCall(verbose=False, log_fn=pytest.helpers.anyvar(int), separator=": ")
for _ in range(3)
])
def test_run_empty_exception(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must raise ExitCode exception on empty status result
"""
args = _default_args(args)
args.exit_code = True
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.core.status.Client.status_get")
mocker.patch("ahriman.core.status.local_client.LocalClient.package_get", return_value=[])
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
_, repository_id = configuration.check_loaded()
Status.run(args, repository_id, configuration, report=False)
check_mock.assert_called_once_with(True, [])
def test_run_verbose(args: argparse.Namespace, configuration: Configuration, repository: Repository,
package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must run command with detailed info
"""
args = _default_args(args)
args.info = True
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.core.status.local_client.LocalClient.package_get",
return_value=[(package_ahriman, BuildStatus(BuildStatusEnum.Success))])
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
_, repository_id = configuration.check_loaded()
Status.run(args, repository_id, configuration, report=False)
print_mock.assert_has_calls([
MockCall(verbose=True, log_fn=pytest.helpers.anyvar(int), separator=": ")
for _ in range(2)
])
def test_run_with_package_filter(args: argparse.Namespace, configuration: Configuration, repository: Repository,
package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must run command with package filter
"""
args = _default_args(args)
args.package = [package_ahriman.base]
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
packages_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_get",
return_value=[(package_ahriman, BuildStatus(BuildStatusEnum.Success))])
_, repository_id = configuration.check_loaded()
Status.run(args, repository_id, configuration, report=False)
packages_mock.assert_called_once_with(package_ahriman.base)
def test_run_by_status(args: argparse.Namespace, configuration: Configuration, repository: Repository,
package_ahriman: Package, package_python_schedule: Package, mocker: MockerFixture) -> None:
"""
must filter packages by status
"""
args = _default_args(args)
args.status = BuildStatusEnum.Failed
mocker.patch("ahriman.core.status.local_client.LocalClient.package_get",
return_value=[(package_ahriman, BuildStatus(BuildStatusEnum.Success)),
(package_python_schedule, BuildStatus(BuildStatusEnum.Failed))])
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
_, repository_id = configuration.check_loaded()
Status.run(args, repository_id, configuration, report=False)
print_mock.assert_has_calls([
MockCall(verbose=False, log_fn=pytest.helpers.anyvar(int), separator=": ")
for _ in range(2)
])
def test_imply_with_report(args: argparse.Namespace, configuration: Configuration, database: SQLite,
mocker: MockerFixture) -> None:
"""
must create application object with native reporting
"""
args = _default_args(args)
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
load_mock = mocker.patch("ahriman.core.repository.Repository.load")
_, repository_id = configuration.check_loaded()
Status.run(args, repository_id, configuration, report=False)
load_mock.assert_called_once_with(repository_id, configuration, database, report=True, refresh_pacman_database=0)
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Status.ALLOW_MULTI_ARCHITECTURE_RUN
@@ -0,0 +1,93 @@
import argparse
from pytest_mock import MockerFixture
from ahriman.application.handlers.status_update import StatusUpdate
from ahriman.core.configuration import Configuration
from ahriman.core.database import SQLite
from ahriman.core.repository import Repository
from ahriman.models.action import Action
from ahriman.models.build_status import BuildStatusEnum
from ahriman.models.package import Package
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.package = None
args.action = Action.Update
args.status = BuildStatusEnum.Success
return args
def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
update_self_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.status_update")
_, repository_id = configuration.check_loaded()
StatusUpdate.run(args, repository_id, configuration, report=False)
update_self_mock.assert_called_once_with(args.status)
def test_run_packages(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must run command with specified packages
"""
args = _default_args(args)
args.package = ["package"]
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
update_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_status_update")
_, repository_id = configuration.check_loaded()
StatusUpdate.run(args, repository_id, configuration, report=False)
update_mock.assert_called_once_with("package", args.status)
def test_run_remove(args: argparse.Namespace, configuration: Configuration, repository: Repository,
package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must remove package from status page
"""
args = _default_args(args)
args.package = [package_ahriman.base]
args.action = Action.Remove
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
update_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_remove")
_, repository_id = configuration.check_loaded()
StatusUpdate.run(args, repository_id, configuration, report=False)
update_mock.assert_called_once_with(package_ahriman.base)
def test_imply_with_report(args: argparse.Namespace, configuration: Configuration, database: SQLite,
mocker: MockerFixture) -> None:
"""
must create application object with native reporting
"""
args = _default_args(args)
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
load_mock = mocker.patch("ahriman.core.repository.Repository.load")
_, repository_id = configuration.check_loaded()
StatusUpdate.run(args, repository_id, configuration, report=False)
load_mock.assert_called_once_with(repository_id, configuration, database, report=True, refresh_pacman_database=0)
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not StatusUpdate.ALLOW_MULTI_ARCHITECTURE_RUN
@@ -0,0 +1,54 @@
import argparse
import pytest
from pytest_mock import MockerFixture
from unittest.mock import call as MockCall
from ahriman.application.handlers.structure import Structure
from ahriman.core.configuration import Configuration
from ahriman.core.repository import Repository
from ahriman.models.package import Package
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.partitions = 1
return args
def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.core.repository.Repository.packages", return_value=[package_ahriman])
packages_mock = mocker.patch("ahriman.core.tree.Tree.partition", return_value=[[package_ahriman]])
application_mock = mocker.patch("ahriman.core.tree.Tree.resolve", return_value=[[package_ahriman]])
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
_, repository_id = configuration.check_loaded()
Structure.run(args, repository_id, configuration, report=False)
packages_mock.assert_called_once_with([package_ahriman], count=args.partitions)
application_mock.assert_called_once_with([package_ahriman])
print_mock.assert_has_calls([
MockCall(verbose=False, log_fn=pytest.helpers.anyvar(int), separator=": "),
MockCall(verbose=True, log_fn=pytest.helpers.anyvar(int), separator=" "),
MockCall(verbose=False, log_fn=pytest.helpers.anyvar(int), separator=": "),
])
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Structure.ALLOW_MULTI_ARCHITECTURE_RUN
@@ -0,0 +1,74 @@
import argparse
from pathlib import Path
from pytest_mock import MockerFixture
from unittest.mock import call as MockCall
from ahriman.application.handlers.tree_migrate import TreeMigrate
from ahriman.core.configuration import Configuration
from ahriman.models.package import Package
from ahriman.models.repository_id import RepositoryId
from ahriman.models.repository_paths import RepositoryPaths
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must run command
"""
tree_create_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
application_mock = mocker.patch("ahriman.application.handlers.tree_migrate.TreeMigrate.tree_move")
symlinks_mock = mocker.patch("ahriman.application.handlers.tree_migrate.TreeMigrate.symlinks_fix")
_, repository_id = configuration.check_loaded()
old_paths = configuration.repository_paths
new_paths = RepositoryPaths(old_paths.root, old_paths.repository_id, _force_current_tree=True)
TreeMigrate.run(args, repository_id, configuration, report=False)
tree_create_mock.assert_called_once_with()
application_mock.assert_called_once_with(old_paths, new_paths)
symlinks_mock.assert_called_once_with(new_paths)
def test_symlinks_fix(repository_paths: RepositoryPaths, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must replace symlinks during migration
"""
mocker.patch("ahriman.application.handlers.tree_migrate.walk", side_effect=[
[
repository_paths.archive_for(package_ahriman.base) / "file",
repository_paths.archive_for(package_ahriman.base) / "symlink",
],
[
repository_paths.repository / "file",
repository_paths.repository / "symlink",
],
])
mocker.patch("pathlib.Path.exists", autospec=True, side_effect=lambda p: p.name == "file")
unlink_mock = mocker.patch("pathlib.Path.unlink")
symlink_mock = mocker.patch("pathlib.Path.symlink_to")
TreeMigrate.symlinks_fix(repository_paths)
unlink_mock.assert_called_once_with()
symlink_mock.assert_called_once_with(
Path("..") /
".." /
".." /
repository_paths.archive_for(package_ahriman.base).relative_to(repository_paths.root) /
"symlink"
)
def test_move_tree(mocker: MockerFixture) -> None:
"""
must move tree
"""
rename_mock = mocker.patch("pathlib.Path.rename", autospec=True)
root = Path("local")
from_paths = RepositoryPaths(root, RepositoryId("arch", ""))
to_paths = RepositoryPaths(root, RepositoryId("arch", "repo"))
TreeMigrate.tree_move(from_paths, to_paths)
rename_mock.assert_has_calls([
MockCall(from_paths.packages, to_paths.packages),
MockCall(from_paths.pacman, to_paths.pacman),
MockCall(from_paths.repository, to_paths.repository),
])
@@ -0,0 +1,57 @@
import argparse
from pytest_mock import MockerFixture
from ahriman.application.handlers.triggers import Triggers
from ahriman.core.configuration import Configuration
from ahriman.core.repository import Repository
from ahriman.models.package import Package
from ahriman.models.result import Result
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.trigger = []
return args
def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
application_mock = mocker.patch("ahriman.application.application.Application.on_result")
on_start_mock = mocker.patch("ahriman.application.application.Application.on_start")
_, repository_id = configuration.check_loaded()
Triggers.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(Result())
on_start_mock.assert_called_once_with()
def test_run_trigger(args: argparse.Namespace, configuration: Configuration, repository: Repository,
package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must run triggers specified by command line
"""
args = _default_args(args)
args.trigger = ["ahriman.core.report.ReportTrigger"]
mocker.patch("ahriman.core.repository.Repository.packages", return_value=[package_ahriman])
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
report_mock = mocker.patch("ahriman.core.report.ReportTrigger.on_result")
upload_mock = mocker.patch("ahriman.core.upload.UploadTrigger.on_result")
_, repository_id = configuration.check_loaded()
Triggers.run(args, repository_id, configuration, report=False)
report_mock.assert_called_once_with(Result(), [package_ahriman])
upload_mock.assert_not_called()
@@ -0,0 +1,90 @@
import argparse
import pytest
from pytest_mock import MockerFixture
from ahriman.application.ahriman import _parser
from ahriman.application.handlers.unsafe_commands import UnsafeCommands
from ahriman.core.configuration import Configuration
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.parser = _parser
args.subcommand = []
return args
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
commands_mock = mocker.patch("ahriman.application.handlers.unsafe_commands.UnsafeCommands.get_unsafe_commands",
return_value=["command"])
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
_, repository_id = configuration.check_loaded()
UnsafeCommands.run(args, repository_id, configuration, report=False)
commands_mock.assert_called_once_with(pytest.helpers.anyvar(int))
print_mock.assert_called_once_with(verbose=True, log_fn=pytest.helpers.anyvar(int), separator=": ")
def test_run_check(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must run command and check if command is unsafe
"""
args = _default_args(args)
args.subcommand = ["clean"]
commands_mock = mocker.patch("ahriman.application.handlers.unsafe_commands.UnsafeCommands.get_unsafe_commands",
return_value=["command"])
check_mock = mocker.patch("ahriman.application.handlers.unsafe_commands.UnsafeCommands.check_unsafe")
_, repository_id = configuration.check_loaded()
UnsafeCommands.run(args, repository_id, configuration, report=False)
commands_mock.assert_called_once_with(pytest.helpers.anyvar(int))
check_mock.assert_called_once_with(["clean"], ["command"], pytest.helpers.anyvar(int))
def test_check_unsafe(mocker: MockerFixture) -> None:
"""
must check if command is unsafe
"""
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
UnsafeCommands.check_unsafe(["service-clean"], ["service-clean"], _parser())
check_mock.assert_called_once_with(True, False)
def test_check_unsafe_safe(mocker: MockerFixture) -> None:
"""
must check if command is safe
"""
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
UnsafeCommands.check_unsafe(["package-status"], ["service-clean"], _parser())
check_mock.assert_called_once_with(True, True)
def test_get_unsafe_commands() -> None:
"""
must return unsafe commands
"""
parser = _parser()
subparser = next(action for action in parser._actions if isinstance(action, argparse._SubParsersAction))
commands = UnsafeCommands.get_unsafe_commands(parser)
for command in commands:
assert subparser.choices[command].get_default("unsafe")
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not UnsafeCommands.ALLOW_MULTI_ARCHITECTURE_RUN
@@ -0,0 +1,161 @@
import argparse
import pytest
from pytest_mock import MockerFixture
from unittest.mock import call as MockCall
from ahriman.application.application import Application
from ahriman.application.handlers.update import Update
from ahriman.core.configuration import Configuration
from ahriman.core.repository import Repository
from ahriman.models.package import Package
from ahriman.models.packagers import Packagers
from ahriman.models.result import Result
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.aur = True
args.changes = True
args.check_files = True
args.package = []
args.dependencies = True
args.dry_run = False
args.exit_code = False
args.increment = True
args.local = True
args.manual = True
args.refresh = 0
args.username = "username"
args.vcs = True
return args
def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
on_start_mock = mocker.patch("ahriman.application.application.Application.on_start")
perform_mock = mocker.patch("ahriman.application.handlers.update.Update.perform_action")
_, repository_id = configuration.check_loaded()
Update.run(args, repository_id, configuration, report=False)
on_start_mock.assert_called_once_with()
perform_mock.assert_called_once_with(pytest.helpers.anyvar(int), args)
def test_perform_action(args: argparse.Namespace, application: Application, package_ahriman: Package,
mocker: MockerFixture) -> None:
"""
must perform update action
"""
args = _default_args(args)
result = Result()
result.add_updated(package_ahriman)
application_mock = mocker.patch("ahriman.application.application.Application.update", return_value=result)
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
dependencies_mock = mocker.patch("ahriman.application.application.Application.with_dependencies",
return_value=[package_ahriman])
updates_mock = mocker.patch("ahriman.application.application.Application.updates", return_value=[package_ahriman])
changes_mock = mocker.patch("ahriman.application.application.Application.changes")
print_mock = mocker.patch("ahriman.application.application.Application.print_updates")
Update.perform_action(application, args)
application_mock.assert_called_once_with([package_ahriman],
Packagers(args.username, {package_ahriman.base: "packager"}),
bump_pkgrel=args.increment)
updates_mock.assert_called_once_with(
args.package, aur=args.aur, local=args.local, manual=args.manual, vcs=args.vcs, check_files=args.check_files)
changes_mock.assert_called_once_with([package_ahriman])
dependencies_mock.assert_called_once_with([package_ahriman], process_dependencies=args.dependencies)
check_mock.assert_called_once_with(False, True)
print_mock.assert_called_once_with([package_ahriman], log_fn=pytest.helpers.anyvar(int))
def test_perform_action_empty_exception(args: argparse.Namespace, application: Application,
mocker: MockerFixture) -> None:
"""
must raise ExitCode exception on empty update list
"""
args = _default_args(args)
args.exit_code = True
args.dry_run = True
mocker.patch("ahriman.application.application.Application.updates", return_value=[])
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
Update.perform_action(application, args)
check_mock.assert_called_once_with(True, [])
def test_perform_action_update_empty_exception(args: argparse.Namespace, application: Application,
package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must raise ExitCode exception on empty build result
"""
args = _default_args(args)
args.exit_code = True
mocker.patch("ahriman.application.application.Application.update", return_value=Result())
mocker.patch("ahriman.application.application.Application.updates", return_value=[package_ahriman])
mocker.patch("ahriman.application.application.Application.with_dependencies", return_value=[package_ahriman])
mocker.patch("ahriman.application.application.Application.print_updates")
mocker.patch("ahriman.application.application.Application.changes")
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
Update.perform_action(application, args)
check_mock.assert_called_once_with(True, False)
def test_perform_action_dry_run(args: argparse.Namespace, application: Application, package_ahriman: Package,
mocker: MockerFixture) -> None:
"""
must run simplified command
"""
args = _default_args(args)
args.dry_run = True
application_mock = mocker.patch("ahriman.application.application.Application.update")
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
updates_mock = mocker.patch("ahriman.application.application.Application.updates", return_value=[package_ahriman])
changes_mock = mocker.patch("ahriman.application.application.Application.changes")
Update.perform_action(application, args)
updates_mock.assert_called_once_with(
args.package, aur=args.aur, local=args.local, manual=args.manual, vcs=args.vcs, check_files=args.check_files)
application_mock.assert_not_called()
changes_mock.assert_called_once_with([package_ahriman])
check_mock.assert_called_once_with(False, [package_ahriman])
def test_perform_action_no_changes(args: argparse.Namespace, application: Application, mocker: MockerFixture) -> None:
"""
must skip changes calculation
"""
args = _default_args(args)
args.dry_run = True
args.changes = False
mocker.patch("ahriman.application.application.Application.update")
mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
mocker.patch("ahriman.application.application.Application.updates")
changes_mock = mocker.patch("ahriman.application.application.Application.changes")
Update.perform_action(application, args)
changes_mock.assert_not_called()
def test_log_fn(application: Application, mocker: MockerFixture) -> None:
"""
must print package updates
"""
logger_mock = mocker.patch("logging.Logger.info")
Update.log_fn(application, False)("hello")
logger_mock.assert_has_calls([MockCall("hello")])
@@ -0,0 +1,182 @@
import argparse
import pytest
from pytest_mock import MockerFixture
from unittest.mock import call as MockCall
from ahriman.application.handlers.users import Users
from ahriman.core.configuration import Configuration
from ahriman.core.database import SQLite
from ahriman.core.exceptions import PasswordError
from ahriman.models.action import Action
from ahriman.models.user import User
from ahriman.models.user_access import UserAccess
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.username = "user"
args.action = Action.Update
args.exit_code = False
args.key = "key"
args.packager = "packager"
args.password = "pa55w0rd"
args.role = UserAccess.Reporter
return args
def test_run(args: argparse.Namespace, configuration: Configuration, database: SQLite, mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
user = User(username=args.username, password=args.password, access=args.role,
packager_id=args.packager, key=args.key)
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
mocker.patch("ahriman.models.user.User.hash_password", return_value=user)
create_user_mock = mocker.patch("ahriman.application.handlers.users.Users.user_create", return_value=user)
update_mock = mocker.patch("ahriman.core.database.SQLite.user_update")
_, repository_id = configuration.check_loaded()
Users.run(args, repository_id, configuration, report=False)
create_user_mock.assert_called_once_with(args)
update_mock.assert_called_once_with(user)
def test_run_empty_salt(args: argparse.Namespace, configuration: Configuration, database: SQLite,
mocker: MockerFixture) -> None:
"""
must process users with empty password salt
"""
configuration.remove_option("auth", "salt")
args = _default_args(args)
user = User(username=args.username, password=args.password, access=args.role,
packager_id=args.packager, key=args.key)
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
mocker.patch("ahriman.models.user.User.hash_password", return_value=user)
create_user_mock = mocker.patch("ahriman.application.handlers.users.Users.user_create", return_value=user)
update_mock = mocker.patch("ahriman.core.database.SQLite.user_update")
_, repository_id = configuration.check_loaded()
Users.run(args, repository_id, configuration, report=False)
create_user_mock.assert_called_once_with(args)
update_mock.assert_called_once_with(user)
def test_run_empty_salt_without_password(args: argparse.Namespace, configuration: Configuration, database: SQLite,
mocker: MockerFixture) -> None:
"""
must skip salt option in case if password was empty
"""
configuration.remove_option("auth", "salt")
args = _default_args(args)
user = User(username=args.username, password="", access=args.role,
packager_id=args.packager, key=args.key)
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
mocker.patch("ahriman.models.user.User.hash_password", return_value=user)
create_user_mock = mocker.patch("ahriman.application.handlers.users.Users.user_create", return_value=user)
update_mock = mocker.patch("ahriman.core.database.SQLite.user_update")
_, repository_id = configuration.check_loaded()
Users.run(args, repository_id, configuration, report=False)
create_user_mock.assert_called_once_with(args)
update_mock.assert_called_once_with(user)
def test_run_list(args: argparse.Namespace, configuration: Configuration, database: SQLite, user: User,
mocker: MockerFixture) -> None:
"""
must list available users
"""
args = _default_args(args)
args.action = Action.List
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
list_mock = mocker.patch("ahriman.core.database.SQLite.user_list", return_value=[user])
_, repository_id = configuration.check_loaded()
Users.run(args, repository_id, configuration, report=False)
list_mock.assert_called_once_with("user", args.role)
check_mock.assert_called_once_with(False, [user])
def test_run_empty_exception(args: argparse.Namespace, configuration: Configuration, database: SQLite,
mocker: MockerFixture) -> None:
"""
must raise ExitCode exception on empty user list
"""
args = _default_args(args)
args.action = Action.List
args.exit_code = True
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
mocker.patch("ahriman.core.database.SQLite.user_list", return_value=[])
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")
_, repository_id = configuration.check_loaded()
Users.run(args, repository_id, configuration, report=False)
check_mock.assert_called_once_with(True, [])
def test_run_remove(args: argparse.Namespace, configuration: Configuration, database: SQLite,
mocker: MockerFixture) -> None:
"""
must remove user if remove flag supplied
"""
args = _default_args(args)
args.action = Action.Remove
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
remove_mock = mocker.patch("ahriman.core.database.SQLite.user_remove")
_, repository_id = configuration.check_loaded()
Users.run(args, repository_id, configuration, report=False)
remove_mock.assert_called_once_with(args.username)
def test_user_create(args: argparse.Namespace, user: User) -> None:
"""
must create user
"""
args = _default_args(args)
generated = Users.user_create(args)
assert generated.username == user.username
assert generated.access == user.access
def test_user_create_getpass(args: argparse.Namespace, mocker: MockerFixture) -> None:
"""
must create user and get password from command line
"""
args = _default_args(args)
args.password = None
getpass_mock = mocker.patch("getpass.getpass", return_value="password")
generated = Users.user_create(args)
getpass_mock.assert_has_calls([MockCall(), MockCall("Repeat password: ")])
assert generated.password == "password"
def test_user_create_getpass_exception(args: argparse.Namespace, mocker: MockerFixture) -> None:
"""
must raise password error in case if password doesn't match
"""
args = _default_args(args)
args.password = None
mocker.patch("getpass.getpass", side_effect=lambda *_: User.generate_password(10))
with pytest.raises(PasswordError):
Users.user_create(args)
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Users.ALLOW_MULTI_ARCHITECTURE_RUN
@@ -0,0 +1,162 @@
import argparse
import json
import pytest
from pathlib import Path
from pytest_mock import MockerFixture
from ahriman.application.handlers.validate import Validate
from ahriman.core.configuration import Configuration
from ahriman.core.configuration.schema import CONFIGURATION_SCHEMA
from ahriman.core.configuration.validator import Validator
from ahriman.core.gitremote import RemotePullTrigger, RemotePushTrigger
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.exit_code = False
return args
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
mocker.patch.object(Validator, "errors", {"node": ["error"]})
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
application_mock = mocker.patch("ahriman.core.configuration.validator.Validator.validate", return_value=False)
_, repository_id = configuration.check_loaded()
Validate.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(configuration.dump())
print_mock.assert_called_once_with(verbose=True, log_fn=pytest.helpers.anyvar(int), separator=": ")
def test_run_skip(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must skip print if no errors found
"""
args = _default_args(args)
mocker.patch("ahriman.core.configuration.validator.Validator.validate", return_value=True)
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
_, repository_id = configuration.check_loaded()
Validate.run(args, repository_id, configuration, report=False)
print_mock.assert_not_called()
def test_run_default(args: argparse.Namespace, configuration: Configuration) -> None:
"""
must run on default configuration without errors
"""
args.exit_code = True
_, repository_id = configuration.check_loaded()
default = Configuration.from_path(Configuration.SYSTEM_CONFIGURATION_PATH, repository_id)
# copy autogenerated values
for section, key in (("build", "build_command"), ("repository", "root")):
value = configuration.get(section, key)
default.set_option(section, key, value)
Validate.run(args, repository_id, default, report=False)
def test_run_repo_specific_triggers(args: argparse.Namespace, configuration: Configuration,
resource_path_root: Path) -> None:
"""
must correctly insert repo specific triggers
"""
args.exit_code = True
_, repository_id = configuration.check_loaded()
# remove unused sections
for section in ("archive", "customs3", "github:x86_64", "logs-rotation", "mirrorlist"):
configuration.remove_section(section)
configuration.set_option("report", "target", "test")
for section in ("test", "test:i686", "test:another-repo:x86_64"):
configuration.set_option(section, "type", "html")
configuration.set_option(section, "link_path", "http://link_path")
configuration.set_option(section, "path", "path")
configuration.set_option(section, "template", "template")
configuration.set_option(section, "templates", str(resource_path_root))
Validate.run(args, repository_id, configuration, report=False)
def test_schema(configuration: Configuration) -> None:
"""
must generate full schema correctly
"""
schema = Validate.schema(configuration)
# defaults
assert schema.pop("console")
assert schema.pop("email")
assert schema.pop("github")
assert schema.pop("gitremote")
assert schema.pop("html")
assert schema.pop("keyring")
assert schema.pop("keyring-generator")
assert schema.pop("mirrorlist")
assert schema.pop("mirrorlist-generator")
assert schema.pop("remote-call")
assert schema.pop("remote-pull")
assert schema.pop("remote-push")
assert schema.pop("remote-service")
assert schema.pop("report")
assert schema.pop("rss")
assert schema.pop("rsync")
assert schema.pop("s3")
assert schema.pop("telegram")
assert schema.pop("upload")
assert schema.pop("worker")
assert schema == CONFIGURATION_SCHEMA
def test_schema_invalid_trigger(configuration: Configuration) -> None:
"""
must skip trigger if it caused exception on load
"""
configuration.set_option("build", "triggers", "some.invalid.trigger.path.Trigger")
configuration.remove_option("build", "triggers_known")
assert Validate.schema(configuration) == CONFIGURATION_SCHEMA
def test_schema_erase_required() -> None:
"""
must remove required field from dictionaries recursively
"""
# the easiest way is to just dump to string and check
assert "required" not in json.dumps(Validate.schema_erase_required(CONFIGURATION_SCHEMA))
def test_schema_merge() -> None:
"""
must merge schemas correctly
"""
erased = Validate.schema_erase_required(CONFIGURATION_SCHEMA)
assert Validate.schema_merge(erased, CONFIGURATION_SCHEMA) == CONFIGURATION_SCHEMA
merged = Validate.schema_merge(RemotePullTrigger.CONFIGURATION_SCHEMA, RemotePushTrigger.CONFIGURATION_SCHEMA)
for key in RemotePullTrigger.CONFIGURATION_SCHEMA["gitremote"]["schema"]:
assert key in merged["gitremote"]["schema"]
for key in RemotePushTrigger.CONFIGURATION_SCHEMA["gitremote"]["schema"]:
assert key in merged["gitremote"]["schema"]
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Validate.ALLOW_MULTI_ARCHITECTURE_RUN
@@ -0,0 +1,50 @@
import argparse
import pytest
from pytest_mock import MockerFixture
from unittest.mock import call as MockCall
from ahriman.application.handlers.versions import Versions
from ahriman.core.configuration import Configuration
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must run command
"""
application_mock = mocker.patch("ahriman.application.handlers.versions.Versions.package_dependencies")
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
_, repository_id = configuration.check_loaded()
Versions.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with("ahriman")
print_mock.assert_has_calls([
MockCall(verbose=False, log_fn=pytest.helpers.anyvar(int), separator=" "),
MockCall(verbose=False, log_fn=pytest.helpers.anyvar(int), separator=" "),
])
def test_package_dependencies() -> None:
"""
must extract package dependencies
"""
packages = dict(Versions.package_dependencies("requests"))
assert packages
assert packages.get("urllib3") is not None
def test_package_dependencies_missing() -> None:
"""
must extract package dependencies even if some of them are missing
"""
packages = dict(Versions.package_dependencies("ahriman"))
assert packages
assert packages.get("pyalpm") is not None
assert packages.get("Sphinx") is None
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Versions.ALLOW_MULTI_ARCHITECTURE_RUN
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,19 @@
from ahriman.application.help_formatter import _HelpFormatter
def test_whitespace_matcher(formatter: _HelpFormatter) -> None:
"""
must only match spaces or tabs
"""
assert formatter._whitespace_matcher.match(" ")
assert formatter._whitespace_matcher.match("\t")
assert formatter._whitespace_matcher.match("\n") is None
assert formatter._whitespace_matcher.match("\r") is None
def test_fill_text(formatter: _HelpFormatter) -> None:
"""
must wrap text keeping new lines
"""
assert formatter._fill_text("first\n 1 longwordhere", 10, "") == "first\n 1 longwor\ndhere"
@@ -0,0 +1,46 @@
from pytest_mock import MockerFixture
from ahriman.application.interactive_shell import InteractiveShell
def test_has_ipython(mocker: MockerFixture) -> None:
"""
must correctly check if IPython is installed
"""
find_spec_mock = mocker.patch("ahriman.application.interactive_shell.find_spec")
assert InteractiveShell.has_ipython()
find_spec_mock.assert_called_once_with("IPython.terminal.embed")
def test_has_ipython_module_not_found(mocker: MockerFixture) -> None:
"""
must return False if IPython is not installed
"""
mocker.patch("ahriman.application.interactive_shell.find_spec", side_effect=ModuleNotFoundError)
assert not InteractiveShell.has_ipython()
def test_interact(mocker: MockerFixture) -> None:
"""
must call IPython shell
"""
mocker.patch("ahriman.application.interactive_shell.InteractiveShell.has_ipython", return_value=True)
banner_mock = mocker.patch("IPython.terminal.embed.InteractiveShellEmbed.show_banner")
interact_mock = mocker.patch("IPython.terminal.embed.InteractiveShellEmbed.interact")
shell = InteractiveShell()
shell.interact()
banner_mock.assert_called_once_with()
interact_mock.assert_called_once_with()
def test_interact_no_ipython(mocker: MockerFixture) -> None:
"""
must call builtin shell if no IPython available
"""
mocker.patch("ahriman.application.interactive_shell.InteractiveShell.has_ipython", return_value=None)
interact_mock = mocker.patch("code.InteractiveConsole.interact")
shell = InteractiveShell()
shell.interact()
interact_mock.assert_called_once_with(shell)
@@ -0,0 +1,296 @@
import argparse
import fcntl
import os
import pytest
from pathlib import Path
from pytest_mock import MockerFixture
from tempfile import NamedTemporaryFile
from unittest.mock import MagicMock, call as MockCall
from ahriman import __version__
from ahriman.application.lock import Lock
from ahriman.core.configuration import Configuration
from ahriman.core.exceptions import DuplicateRunError, UnsafeRunError
from ahriman.models.build_status import BuildStatus, BuildStatusEnum
from ahriman.models.internal_status import InternalStatus
from ahriman.models.repository_id import RepositoryId
def test_path(args: argparse.Namespace, configuration: Configuration) -> None:
"""
must create path variable correctly
"""
_, repository_id = configuration.check_loaded()
assert Lock(args, repository_id, configuration).path is None
args.lock = Path("/run/ahriman.pid")
assert Lock(args, repository_id, configuration).path == Path("/run/ahriman_x86_64-aur.pid")
args.lock = Path("ahriman.pid")
assert Lock(args, repository_id, configuration).path == Path("/run/ahriman/ahriman_x86_64-aur.pid")
assert Lock(args, RepositoryId("", ""), configuration).path == Path("/run/ahriman/ahriman.pid")
with pytest.raises(ValueError):
args.lock = Path("/")
assert Lock(args, repository_id, configuration).path # special case
def test_perform_lock(mocker: MockerFixture) -> None:
"""
must lock file with fcntl
"""
flock_mock = mocker.patch("fcntl.flock")
assert Lock.perform_lock(1)
flock_mock.assert_called_once_with(1, fcntl.LOCK_EX | fcntl.LOCK_NB)
def test_perform_lock_exception(mocker: MockerFixture) -> None:
"""
must return False on OSError
"""
mocker.patch("fcntl.flock", side_effect=OSError)
assert not Lock.perform_lock(1)
def test_open(lock: Lock, mocker: MockerFixture) -> None:
"""
must open file
"""
open_mock = mocker.patch("pathlib.Path.open")
lock.path = Path("ahriman.pid")
lock._open()
open_mock.assert_called_once_with("a+", encoding="utf8")
def test_open_skip(lock: Lock, mocker: MockerFixture) -> None:
"""
must skip file opening if path is not set
"""
open_mock = mocker.patch("pathlib.Path.open")
lock._open()
open_mock.assert_not_called()
def test_watch(lock: Lock, mocker: MockerFixture) -> None:
"""
must check if lock file exists
"""
lock._pid_file = MagicMock()
lock._pid_file.fileno.return_value = 1
wait_mock = mocker.patch("ahriman.models.waiter.Waiter.wait")
lock._watch()
wait_mock.assert_called_once_with(pytest.helpers.anyvar(int), 1)
def test_watch_skip(lock: Lock, mocker: MockerFixture) -> None:
"""
must skip watch on empty path
"""
mocker.patch("ahriman.application.lock.Lock.perform_lock", return_value=True)
lock._watch()
def test_write(lock: Lock) -> None:
"""
must write PID to lock file
"""
with NamedTemporaryFile("a+") as pid_file:
lock._pid_file = pid_file
lock._write(is_locked=False)
assert int(lock._pid_file.readline()) == os.getpid()
def test_write_skip(lock: Lock) -> None:
"""
must skip write to file if no path set
"""
lock._write(is_locked=False)
def test_write_locked(lock: Lock, mocker: MockerFixture) -> None:
"""
must raise DuplicateRunError if it cannot lock file
"""
mocker.patch("ahriman.application.lock.Lock.perform_lock", return_value=False)
with pytest.raises(DuplicateRunError):
lock._pid_file = MagicMock()
lock._write(is_locked=False)
def test_write_locked_before(lock: Lock, mocker: MockerFixture) -> None:
"""
must skip lock in case if file was locked before
"""
lock_mock = mocker.patch("ahriman.application.lock.Lock.perform_lock")
lock._pid_file = MagicMock()
lock._write(is_locked=True)
lock_mock.assert_not_called()
def test_check_user(lock: Lock, mocker: MockerFixture) -> None:
"""
must check user correctly
"""
check_user_patch = mocker.patch("ahriman.application.lock.check_user")
tree_create = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
lock.check_user()
check_user_patch.assert_called_once_with(lock.paths.root, unsafe=False)
tree_create.assert_called_once_with()
def test_check_user_exception(lock: Lock, mocker: MockerFixture) -> None:
"""
must raise exception if user differs
"""
mocker.patch("ahriman.application.lock.check_user", side_effect=UnsafeRunError(0, 1))
with pytest.raises(UnsafeRunError):
lock.check_user()
def test_check_user_unsafe(lock: Lock, mocker: MockerFixture) -> None:
"""
must skip user check if unsafe flag set
"""
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
lock.unsafe = True
lock.check_user()
def test_check_version(lock: Lock, mocker: MockerFixture) -> None:
"""
must check version correctly
"""
mocker.patch("ahriman.core.status.Client.status_get",
return_value=InternalStatus(status=BuildStatus(), version=__version__))
logging_mock = mocker.patch("logging.Logger.warning")
lock.check_version()
logging_mock.assert_not_called()
def test_check_version_mismatch(lock: Lock, mocker: MockerFixture) -> None:
"""
must check mismatched version correctly
"""
mocker.patch("ahriman.core.status.Client.status_get",
return_value=InternalStatus(status=BuildStatus(), version="version"))
logging_mock = mocker.patch("logging.Logger.warning")
lock.check_version()
logging_mock.assert_called_once() # we do not check logging arguments
def test_clear(lock: Lock) -> None:
"""
must remove lock file
"""
lock.path = Path("ahriman-test.pid")
lock.path.touch()
lock.clear()
assert not lock.path.is_file()
def test_clear_missing(lock: Lock) -> None:
"""
must not fail on lock removal if file is missing
"""
lock.path = Path("ahriman-test.pid")
lock.clear()
def test_clear_skip(lock: Lock, mocker: MockerFixture) -> None:
"""
must skip removal if no file set
"""
unlink_mock = mocker.patch("pathlib.Path.unlink")
lock.clear()
unlink_mock.assert_not_called()
def test_clear_close(lock: Lock) -> None:
"""
must close pid file if opened
"""
close_mock = lock._pid_file = MagicMock()
lock.clear()
close_mock.close.assert_called_once_with()
def test_clear_close_exception(lock: Lock) -> None:
"""
must suppress IO exception on file closure
"""
close_mock = lock._pid_file = MagicMock()
close_mock.close.side_effect = IOError
lock.clear()
def test_lock(lock: Lock, mocker: MockerFixture) -> None:
"""
must perform lock correctly
"""
clear_mock = mocker.patch("ahriman.application.lock.Lock.clear")
open_mock = mocker.patch("ahriman.application.lock.Lock._open")
watch_mock = mocker.patch("ahriman.application.lock.Lock._watch", return_value=True)
write_mock = mocker.patch("ahriman.application.lock.Lock._write")
lock.lock()
clear_mock.assert_not_called()
open_mock.assert_called_once_with()
watch_mock.assert_called_once_with()
write_mock.assert_called_once_with(is_locked=True)
def test_lock_clear(lock: Lock, mocker: MockerFixture) -> None:
"""
must clear lock file before lock if force flag is set
"""
mocker.patch("ahriman.application.lock.Lock._open")
mocker.patch("ahriman.application.lock.Lock._watch")
mocker.patch("ahriman.application.lock.Lock._write")
clear_mock = mocker.patch("ahriman.application.lock.Lock.clear")
lock.force = True
lock.lock()
clear_mock.assert_called_once_with()
def test_enter(lock: Lock, mocker: MockerFixture) -> None:
"""
must process with context manager
"""
check_user_mock = mocker.patch("ahriman.application.lock.Lock.check_user")
check_version_mock = mocker.patch("ahriman.application.lock.Lock.check_version")
lock_mock = mocker.patch("ahriman.application.lock.Lock.lock")
update_status_mock = mocker.patch("ahriman.core.status.Client.status_update")
with lock:
pass
check_user_mock.assert_called_once_with()
check_version_mock.assert_called_once_with()
lock_mock.assert_called_once_with()
update_status_mock.assert_has_calls([MockCall(BuildStatusEnum.Building), MockCall(BuildStatusEnum.Success)])
def test_exit_with_exception(lock: Lock, mocker: MockerFixture) -> None:
"""
must process with context manager in case if exception raised
"""
mocker.patch("ahriman.application.lock.Lock.check_user")
mocker.patch("ahriman.application.lock.Lock.clear")
mocker.patch("ahriman.application.lock.Lock.lock")
update_status_mock = mocker.patch("ahriman.core.status.Client.status_update")
with pytest.raises(ValueError):
with lock:
raise ValueError()
update_status_mock.assert_has_calls([MockCall(BuildStatusEnum.Building), MockCall(BuildStatusEnum.Failed)])