feat: allow to use one application for multiple repositories (#111)

* allow to use one application for multiple repositories

* update tests

* handle None append argument everywhere

* rewrite repository definition logic

* drop optional flags from docs

* support of new schema in systemd units

* add migration docs and ability to migrate tree automatically

* use repostory id instead

* verbose multiarchitectureerror

* object path support for s3 sync

* fix tests after rebase
This commit is contained in:
2023-09-08 03:42:28 +03:00
parent c915d68c97
commit efde0b2e86
191 changed files with 3441 additions and 1319 deletions

View File

@ -27,7 +27,8 @@ def application_packages(configuration: Configuration, database: SQLite, reposit
"""
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
return ApplicationPackages("x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
return ApplicationPackages(repository_id, configuration, report=False)
@pytest.fixture
@ -47,7 +48,8 @@ def application_properties(configuration: Configuration, database: SQLite, repos
"""
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
return ApplicationProperties("x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
return ApplicationProperties(repository_id, configuration, report=False)
@pytest.fixture
@ -67,4 +69,5 @@ def application_repository(configuration: Configuration, database: SQLite, repos
"""
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
return ApplicationRepository("x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
return ApplicationRepository(repository_id, configuration, report=False)

View File

@ -6,3 +6,10 @@ def test_create_tree(application_properties: ApplicationProperties) -> None:
must have repository attribute
"""
assert application_properties.repository
def test_architecture(application_properties: ApplicationProperties) -> None:
"""
must return repository architecture
"""
assert application_properties.architecture == application_properties.repository_id.architecture

View File

@ -28,7 +28,8 @@ def application(configuration: Configuration, repository: Repository, database:
"""
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
return Application("x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
return Application(repository_id, configuration, report=False)
@pytest.fixture
@ -39,7 +40,8 @@ def args() -> argparse.Namespace:
Returns:
argparse.Namespace: command line arguments test instance
"""
return argparse.Namespace(architecture=None, lock=None, force=False, unsafe=False, report=False, wait_timeout=-1)
return argparse.Namespace(architecture=None, lock=None, force=False, unsafe=False, report=False,
repository=None, repository_id=None, wait_timeout=-1)
@pytest.fixture
@ -54,7 +56,8 @@ def lock(args: argparse.Namespace, configuration: Configuration) -> Lock:
Returns:
Lock: file lock test instance
"""
return Lock(args, "x86_64", configuration)
_, repository_id = configuration.check_loaded()
return Lock(args, repository_id, configuration)
@pytest.fixture

View File

@ -8,48 +8,7 @@ from ahriman.application.handlers import Handler
from ahriman.core.configuration import Configuration
from ahriman.core.exceptions import ExitCode, MissingArchitectureError, MultipleArchitecturesError
from ahriman.models.log_handler import LogHandler
def test_architectures_extract(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must generate list of available architectures
"""
args.configuration = configuration.path
known_architectures_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures")
Handler.architectures_extract(args)
known_architectures_mock.assert_called_once_with(configuration.getpath("repository", "root"))
def test_architectures_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.models.repository_paths.RepositoryPaths.known_architectures", return_value=set())
with pytest.raises(MissingArchitectureError):
Handler.architectures_extract(args)
def test_architectures_extract_exception(args: argparse.Namespace, mocker: MockerFixture) -> None:
"""
must raise exception on missing architectures
"""
args.command = "config"
mocker.patch.object(Handler, "ALLOW_AUTO_ARCHITECTURE_RUN", False)
with pytest.raises(MissingArchitectureError):
Handler.architectures_extract(args)
def test_architectures_extract_specified(args: argparse.Namespace) -> None:
"""
must return architecture list if it has been specified
"""
architectures = args.architecture = ["i686", "x86_64"]
assert Handler.architectures_extract(args) == sorted(set(architectures))
from ahriman.models.repository_id import RepositoryId
def test_call(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
@ -62,20 +21,21 @@ def test_call(args: argparse.Namespace, configuration: Configuration, mocker: Mo
args.report = False
mocker.patch("ahriman.application.handlers.Handler.run")
configuration_mock = mocker.patch("ahriman.core.configuration.Configuration.from_path", return_value=configuration)
log_handler_mock = mocker.patch("ahriman.core.log.Log.handler", return_value=args.log_handler)
log_load_mock = mocker.patch("ahriman.core.log.Log.load")
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__")
assert Handler.call(args, "x86_64")
configuration_mock.assert_called_once_with(args.configuration, "x86_64")
_, 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(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, mocker: MockerFixture) -> None:
def test_call_exception(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must process exception
"""
@ -84,11 +44,12 @@ def test_call_exception(args: argparse.Namespace, mocker: MockerFixture) -> None
mocker.patch("ahriman.core.configuration.Configuration.from_path", side_effect=Exception())
logging_mock = mocker.patch("logging.Logger.exception")
assert not Handler.call(args, "x86_64")
_, 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, mocker: MockerFixture) -> None:
def test_call_exit_code(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must process exitcode exception
"""
@ -97,7 +58,8 @@ def test_call_exit_code(args: argparse.Namespace, mocker: MockerFixture) -> None
mocker.patch("ahriman.core.configuration.Configuration.from_path", side_effect=ExitCode())
logging_mock = mocker.patch("logging.Logger.exception")
assert not Handler.call(args, "x86_64")
_, repository_id = configuration.check_loaded()
assert not Handler.call(args, repository_id)
logging_mock.assert_not_called()
@ -105,33 +67,39 @@ def test_execute(args: argparse.Namespace, mocker: MockerFixture) -> None:
"""
must run execution in multiple processes
"""
args.architecture = ["i686", "x86_64"]
ids = [
RepositoryId("i686", "aur-clone"),
RepositoryId("x86_64", "aur-clone"),
]
mocker.patch("ahriman.application.handlers.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, architecture) for architecture in args.architecture])
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.architecture = ["i686", "x86_64"]
args.command = "web"
mocker.patch("ahriman.application.handlers.Handler.repositories_extract", return_value=[
RepositoryId("i686", "aur-clone"),
RepositoryId("x86_64", "aur-clone"),
])
mocker.patch.object(Handler, "ALLOW_MULTI_ARCHITECTURE_RUN", False)
with pytest.raises(MultipleArchitecturesError):
Handler.execute(args)
def test_execute_single(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
def test_execute_single(args: argparse.Namespace, mocker: MockerFixture) -> None:
"""
must run execution in current process if only one architecture supplied
"""
args.architecture = ["x86_64"]
args.configuration = Path("")
args.quiet = False
mocker.patch("ahriman.core.configuration.Configuration.from_path", return_value=configuration)
mocker.patch("ahriman.application.handlers.Handler.repositories_extract", return_value=[
RepositoryId("x86_64", "aur-clone"),
])
starmap_mock = mocker.patch("multiprocessing.pool.Pool.starmap")
Handler.execute(args)
@ -142,8 +110,117 @@ 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, "x86_64", configuration, report=True)
Handler.run(args, repository_id, configuration, report=True)
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"]
known_architectures_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures")
known_repositories_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_repositories")
assert Handler.repositories_extract(args) == [RepositoryId("arch", "repo")]
known_architectures_mock.assert_not_called()
known_repositories_mock.assert_not_called()
def test_repositories_extract_repository(args: argparse.Namespace, configuration: Configuration,
mocker: MockerFixture) -> None:
"""
must generate list of available repositories based on flags and tree
"""
args.architecture = ["arch"]
args.configuration = configuration.path
known_architectures_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures")
known_repositories_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_repositories",
return_value={"repo"})
assert Handler.repositories_extract(args) == [RepositoryId("arch", "repo")]
known_architectures_mock.assert_not_called()
known_repositories_mock.assert_called_once_with(configuration.repository_paths.root)
def test_repositories_extract_repository_legacy(args: argparse.Namespace, configuration: Configuration,
mocker: MockerFixture) -> None:
"""
must generate list of available repositories based on flags and tree
"""
args.architecture = ["arch"]
args.configuration = configuration.path
known_architectures_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures")
known_repositories_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_repositories",
return_value=set())
assert Handler.repositories_extract(args) == [RepositoryId("arch", "aur-clone")]
known_architectures_mock.assert_not_called()
known_repositories_mock.assert_called_once_with(configuration.repository_paths.root)
def test_repositories_extract_architecture(args: argparse.Namespace, configuration: Configuration,
mocker: MockerFixture) -> None:
"""
must read repository name from config
"""
args.configuration = configuration.path
args.repository = ["repo"]
known_architectures_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures",
return_value={"arch"})
known_repositories_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_repositories")
assert Handler.repositories_extract(args) == [RepositoryId("arch", "repo")]
known_architectures_mock.assert_called_once_with(configuration.repository_paths.root, "repo")
known_repositories_mock.assert_not_called()
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.models.repository_paths.RepositoryPaths.known_architectures", return_value=set())
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_repositories", return_value=set())
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"
known_architectures_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures")
known_repositories_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_repositories")
assert Handler.repositories_extract(args) == [RepositoryId("i686", "some-repo-name")]
known_architectures_mock.assert_not_called()
known_repositories_mock.assert_not_called()
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"
known_architectures_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures")
known_repositories_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_repositories",
return_value=set())
assert Handler.repositories_extract(args) == [RepositoryId("i686", "aur-clone")]
known_architectures_mock.assert_not_called()
known_repositories_mock.assert_called_once_with(configuration.repository_paths.root)
def test_check_if_empty() -> None:

View File

@ -44,7 +44,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
dependencies_mock = mocker.patch("ahriman.application.application.Application.with_dependencies")
on_start_mock = mocker.patch("ahriman.application.application.Application.on_start")
Add.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Add.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(args.package, args.source, args.username)
dependencies_mock.assert_not_called()
on_start_mock.assert_called_once_with()
@ -68,7 +69,8 @@ def test_run_with_updates(args: argparse.Namespace, configuration: Configuration
return_value=[package_ahriman])
print_mock = mocker.patch("ahriman.application.application.Application.print_updates")
Add.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Add.run(args, repository_id, configuration, report=False)
updates_mock.assert_called_once_with(args.package, aur=False, local=False, manual=True, vcs=False)
application_mock.assert_called_once_with([package_ahriman],
Packagers(args.username, {package_ahriman.base: "packager"}),
@ -94,5 +96,6 @@ def test_run_empty_exception(args: argparse.Namespace, configuration: Configurat
mocker.patch("ahriman.application.application.Application.print_updates")
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
Add.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Add.run(args, repository_id, configuration, report=False)
check_mock.assert_called_once_with(True, True)

View File

@ -33,7 +33,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
add_mock = tarfile.__enter__.return_value = MagicMock()
mocker.patch("tarfile.TarFile.__new__", return_value=tarfile)
Backup.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Backup.run(args, repository_id, configuration, report=False)
add_mock.add.assert_called_once_with(Path("path"))
@ -55,8 +56,8 @@ def test_get_paths(configuration: Configuration, mocker: MockerFixture) -> None:
assert all(path.exists() for path in paths if path.name not in (".gnupg", "cache"))
def test_disallow_auto_architecture_run() -> None:
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Backup.ALLOW_AUTO_ARCHITECTURE_RUN
assert not Backup.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -35,6 +35,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
application_mock = mocker.patch("ahriman.application.application.Application.clean")
on_start_mock = mocker.patch("ahriman.application.application.Application.on_start")
Clean.run(args, "x86_64", configuration, report=False)
_, 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()

View File

@ -33,7 +33,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
start_mock = mocker.patch("threading.Timer.start")
join_mock = mocker.patch("threading.Timer.join")
Daemon.run(args, "x86_64", configuration, report=True)
run_mock.assert_called_once_with(args, "x86_64", configuration, report=True)
_, 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)
start_mock.assert_called_once_with()
join_mock.assert_called_once_with()

View File

@ -29,13 +29,14 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
application_mock = mocker.patch("ahriman.core.configuration.Configuration.dump",
return_value=configuration.dump())
Dump.run(args, "x86_64", configuration, report=False)
_, 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_disallow_auto_architecture_run() -> None:
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Dump.ALLOW_AUTO_ARCHITECTURE_RUN
assert not Dump.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -29,7 +29,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
args = _default_args(args)
parse_mock = mocker.patch("argparse.ArgumentParser.parse_args")
Help.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Help.run(args, repository_id, configuration, report=False)
parse_mock.assert_called_once_with(["--help"])
@ -41,12 +42,13 @@ def test_run_command(args: argparse.Namespace, configuration: Configuration, moc
args.command = "aur-search"
parse_mock = mocker.patch("argparse.ArgumentParser.parse_args")
Help.run(args, "x86_64", configuration, report=False)
_, 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_auto_architecture_run() -> None:
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Help.ALLOW_AUTO_ARCHITECTURE_RUN
assert not Help.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -31,12 +31,13 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
application_mock = mocker.patch("ahriman.core.sign.gpg.GPG.key_import")
KeyImport.run(args, "x86_64", configuration, report=False)
_, 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_auto_architecture_run() -> None:
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not KeyImport.ALLOW_AUTO_ARCHITECTURE_RUN
assert not KeyImport.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -44,8 +44,9 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
return_value=(args.package, PkgbuildPatch(None, "patch")))
application_mock = mocker.patch("ahriman.application.handlers.Patch.patch_set_create")
Patch.run(args, "x86_64", configuration, report=False)
patch_mock.assert_called_once_with(args.package, "x86_64", args.track)
_, 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"))
@ -63,7 +64,8 @@ def test_run_function(args: argparse.Namespace, configuration: Configuration, re
patch_mock = mocker.patch("ahriman.application.handlers.Patch.patch_create_from_function", return_value=patch)
application_mock = mocker.patch("ahriman.application.handlers.Patch.patch_set_create")
Patch.run(args, "x86_64", configuration, report=False)
_, 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)
@ -79,7 +81,8 @@ def test_run_list(args: argparse.Namespace, configuration: Configuration, reposi
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
application_mock = mocker.patch("ahriman.application.handlers.Patch.patch_set_list")
Patch.run(args, "x86_64", configuration, report=False)
_, 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)
@ -94,11 +97,12 @@ def test_run_remove(args: argparse.Namespace, configuration: Configuration, repo
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
application_mock = mocker.patch("ahriman.application.handlers.Patch.patch_set_remove")
Patch.run(args, "x86_64", configuration, report=False)
_, 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, mocker: MockerFixture) -> None:
def test_patch_create_from_diff(package_ahriman: Package, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must create patch from directory tree diff
"""
@ -108,8 +112,9 @@ def test_patch_create_from_diff(package_ahriman: Package, mocker: MockerFixture)
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)
assert Patch.patch_create_from_diff(path, "x86_64", ["*.diff"]) == (package_ahriman.base, patch)
package_mock.assert_called_once_with(path, "x86_64", None)
_, 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")
@ -185,3 +190,10 @@ def test_patch_set_remove(application: Application, package_ahriman: Package, mo
remove_mock = mocker.patch("ahriman.core.database.SQLite.patches_remove")
Patch.patch_set_remove(application, package_ahriman.base, ["version"])
remove_mock.assert_called_once_with(package_ahriman.base, ["version"])
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Patch.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -23,7 +23,7 @@ def _default_args(args: argparse.Namespace) -> argparse.Namespace:
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.depends_on = []
args.depends_on = None
args.dry_run = False
args.from_database = False
args.exit_code = False
@ -49,7 +49,8 @@ def test_run(args: argparse.Namespace, package_ahriman: Package, configuration:
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
on_start_mock = mocker.patch("ahriman.application.application.Application.on_start")
Rebuild.run(args, "x86_64", configuration, report=False)
_, 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], args.username, bump_pkgrel=args.increment)
@ -70,7 +71,8 @@ def test_run_extract_packages(args: argparse.Namespace, configuration: Configura
mocker.patch("ahriman.application.application.Application.print_updates")
extract_mock = mocker.patch("ahriman.application.handlers.Rebuild.extract_packages", return_value=[])
Rebuild.run(args, "x86_64", configuration, report=False)
_, 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)
@ -87,7 +89,8 @@ def test_run_dry_run(args: argparse.Namespace, configuration: Configuration, rep
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
print_mock = mocker.patch("ahriman.application.application.Application.print_updates")
Rebuild.run(args, "x86_64", configuration, report=False)
_, 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, False)
print_mock.assert_called_once_with([package_ahriman], log_fn=pytest.helpers.anyvar(int))
@ -105,7 +108,8 @@ def test_run_filter(args: argparse.Namespace, configuration: Configuration, repo
mocker.patch("ahriman.application.handlers.Rebuild.extract_packages", return_value=[])
application_packages_mock = mocker.patch("ahriman.core.repository.repository.Repository.packages_depend_on")
Rebuild.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Rebuild.run(args, repository_id, configuration, report=False)
application_packages_mock.assert_called_once_with([], ["python-aur"])
@ -120,7 +124,8 @@ def test_run_without_filter(args: argparse.Namespace, configuration: Configurati
mocker.patch("ahriman.application.handlers.Rebuild.extract_packages", return_value=[])
application_packages_mock = mocker.patch("ahriman.core.repository.repository.Repository.packages_depend_on")
Rebuild.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Rebuild.run(args, repository_id, configuration, report=False)
application_packages_mock.assert_called_once_with([], None)
@ -138,7 +143,8 @@ def test_run_update_empty_exception(args: argparse.Namespace, configuration: Con
mocker.patch("ahriman.application.application.Application.print_updates")
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
Rebuild.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Rebuild.run(args, repository_id, configuration, report=False)
check_mock.assert_called_once_with(True, True)
@ -155,7 +161,8 @@ def test_run_build_empty_exception(args: argparse.Namespace, configuration: Conf
mocker.patch("ahriman.application.application.Application.update", return_value=Result())
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
Rebuild.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Rebuild.run(args, repository_id, configuration, report=False)
check_mock.assert_has_calls([MockCall(True, False), MockCall(True, True)])

View File

@ -31,6 +31,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
application_mock = mocker.patch("ahriman.application.application.Application.remove")
on_start_mock = mocker.patch("ahriman.application.application.Application.on_start")
Remove.run(args, "x86_64", configuration, report=False)
_, 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()

View File

@ -34,7 +34,8 @@ def test_run(args: argparse.Namespace, package_ahriman: Package, configuration:
remove_mock = mocker.patch("ahriman.application.application.Application.remove")
on_start_mock = mocker.patch("ahriman.application.application.Application.on_start")
RemoveUnknown.run(args, "x86_64", configuration, report=False)
_, 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()
@ -53,7 +54,8 @@ def test_run_dry_run(args: argparse.Namespace, configuration: Configuration, rep
remove_mock = mocker.patch("ahriman.application.application.Application.remove")
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
RemoveUnknown.run(args, "x86_64", configuration, report=False)
_, 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)

View File

@ -32,12 +32,13 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
extract_mock = tarfile.__enter__.return_value = MagicMock()
mocker.patch("tarfile.TarFile.__new__", return_value=tarfile)
Restore.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Restore.run(args, repository_id, configuration, report=False)
extract_mock.extractall.assert_called_once_with(path=args.output)
def test_disallow_auto_architecture_run() -> None:
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Restore.ALLOW_AUTO_ARCHITECTURE_RUN
assert not Restore.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -42,7 +42,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
Search.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Search.run(args, repository_id, configuration, report=False)
aur_search_mock.assert_called_once_with("ahriman", pacman=pytest.helpers.anyvar(int))
official_search_mock.assert_called_once_with("ahriman", pacman=pytest.helpers.anyvar(int))
check_mock.assert_called_once_with(False, False)
@ -62,7 +63,8 @@ def test_run_empty_exception(args: argparse.Namespace, configuration: Configurat
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
Search.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Search.run(args, repository_id, configuration, report=False)
check_mock.assert_called_once_with(True, True)
@ -77,7 +79,8 @@ def test_run_sort(args: argparse.Namespace, configuration: Configuration, reposi
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
sort_mock = mocker.patch("ahriman.application.handlers.Search.sort")
Search.run(args, "x86_64", configuration, report=False)
_, 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__()
@ -96,7 +99,8 @@ def test_run_sort_by(args: argparse.Namespace, configuration: Configuration, rep
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
sort_mock = mocker.patch("ahriman.application.handlers.Search.sort")
Search.run(args, "x86_64", configuration, report=False)
_, 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__()
@ -124,11 +128,11 @@ def test_sort_exception(aur_package_ahriman: AURPackage) -> None:
Search.sort([aur_package_ahriman], "random_field")
def test_disallow_auto_architecture_run() -> None:
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Search.ALLOW_AUTO_ARCHITECTURE_RUN
assert not Search.ALLOW_MULTI_ARCHITECTURE_RUN
def test_sort_fields(aur_package_ahriman: AURPackage) -> None:

View File

@ -35,7 +35,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
application_mock = mocker.patch("ahriman.core.formatters.Printer.print")
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
ServiceUpdates.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
ServiceUpdates.run(args, repository_id, configuration, report=False)
package_mock.assert_called_once_with(package_ahriman.base, repository.pacman, None)
application_mock.assert_called_once_with(verbose=True, separator=" -> ")
check_mock.assert_called_once_with(args.exit_code, True)
@ -53,6 +54,14 @@ def test_run_skip(args: argparse.Namespace, configuration: Configuration, reposi
application_mock = mocker.patch("ahriman.core.formatters.Printer.print")
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
ServiceUpdates.run(args, "x86_64", configuration, report=False)
_, 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

View File

@ -8,7 +8,9 @@ from unittest.mock import call as MockCall
from ahriman.application.handlers import Setup
from ahriman.core.configuration import Configuration
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
@ -23,15 +25,15 @@ def _default_args(args: argparse.Namespace) -> argparse.Namespace:
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.architecture = ["x86_64"]
args.build_as_user = "ahriman"
args.build_command = "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 = "John Doe <john@doe.com>"
args.repository = "aur-clone"
args.repository = ["aur-clone"]
args.server = None
args.sign_key = "key"
args.sign_target = [SignSettings.Packages]
@ -54,17 +56,36 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
executable_mock = mocker.patch("ahriman.application.handlers.Setup.executable_create")
init_mock = mocker.patch("ahriman.core.alpm.repo.Repo.init")
Setup.run(args, "x86_64", configuration, report=False)
ahriman_configuration_mock.assert_called_once_with(args, "x86_64", args.repository, configuration)
_, repository_id = configuration.check_loaded()
Setup.run(args, repository_id, configuration, report=False)
ahriman_configuration_mock.assert_called_once_with(args, repository_id, configuration)
devtools_configuration_mock.assert_called_once_with(
args.build_command, "x86_64", args.from_configuration, args.mirror, args.multilib, args.repository,
f"file://{repository_paths.repository}")
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, args.build_command, "x86_64")
executable_mock.assert_called_once_with(repository_paths, args.build_command, "x86_64")
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,
mocker: MockerFixture) -> None:
"""
@ -80,21 +101,20 @@ def test_run_with_server(args: argparse.Namespace, configuration: Configuration,
mocker.patch("ahriman.core.alpm.repo.Repo.init")
devtools_configuration_mock = mocker.patch("ahriman.application.handlers.Setup.configuration_create_devtools")
Setup.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Setup.run(args, repository_id, configuration, report=False)
devtools_configuration_mock.assert_called_once_with(
args.build_command, "x86_64", args.from_configuration, args.mirror, args.multilib, args.repository,
"server")
repository_id, args.from_configuration, args.mirror, args.multilib, "server")
def test_build_command(args: argparse.Namespace) -> None:
def test_build_command(repository_id: RepositoryId) -> None:
"""
must generate correct build command name
"""
args = _default_args(args)
path = Path("local")
build_command = Setup.build_command(path, args.build_command, "x86_64")
assert build_command.name == f"{args.build_command}-x86_64-build"
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
@ -107,19 +127,26 @@ def test_configuration_create_ahriman(args: argparse.Namespace, configuration: C
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")
command = Setup.build_command(repository_paths.root, args.build_command, "x86_64")
_, repository_id = configuration.check_loaded()
command = Setup.build_command(repository_paths.root, repository_id)
Setup.configuration_create_ahriman(args, "x86_64", args.repository, configuration)
Setup.configuration_create_ahriman(args, repository_id, configuration)
set_option_mock.assert_has_calls([
MockCall(Configuration.section_name("build", "x86_64"), "build_command", str(command)),
MockCall("repository", "name", args.repository),
MockCall(Configuration.section_name("build", "x86_64"), "makechrootpkg_flags", f"-U {args.build_as_user}"),
MockCall(Configuration.section_name("alpm", "x86_64"), "mirror", args.mirror),
MockCall(Configuration.section_name("sign", "x86_64"), "target",
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", "x86_64"), "key", args.sign_key),
MockCall(Configuration.section_name("web", "x86_64"), "port", str(args.web_port)),
MockCall(Configuration.section_name("web", "x86_64"), "unix_socket", str(args.web_unix_socket)),
MockCall(Configuration.section_name("sign", repository_id.name, repository_id.architecture), "key",
args.sign_key),
MockCall(Configuration.section_name("web", repository_id.name, repository_id.architecture), "port",
str(args.web_port)),
MockCall(Configuration.section_name("web", repository_id.name, repository_id.architecture), "unix_socket",
str(args.web_unix_socket)),
MockCall("auth", "salt", pytest.helpers.anyvar(str, strict=True)),
])
write_mock.assert_called_once_with(pytest.helpers.anyvar(int))
@ -136,13 +163,16 @@ def test_configuration_create_ahriman_no_multilib(args: argparse.Namespace, conf
mocker.patch("ahriman.core.configuration.Configuration.write")
set_option_mock = mocker.patch("ahriman.core.configuration.Configuration.set_option")
Setup.configuration_create_ahriman(args, "x86_64", args.repository, configuration)
_, repository_id = configuration.check_loaded()
Setup.configuration_create_ahriman(args, repository_id, configuration)
set_option_mock.assert_has_calls([
MockCall(Configuration.section_name("alpm", "x86_64"), "mirror", args.mirror),
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, mocker: MockerFixture) -> None:
def test_configuration_create_devtools(args: argparse.Namespace, configuration: Configuration,
mocker: MockerFixture) -> None:
"""
must create configuration for the devtools
"""
@ -152,13 +182,14 @@ def test_configuration_create_devtools(args: argparse.Namespace, mocker: MockerF
add_section_mock = mocker.patch("ahriman.core.configuration.Configuration.add_section")
write_mock = mocker.patch("ahriman.core.configuration.Configuration.write")
Setup.configuration_create_devtools(args.build_command, "x86_64", args.from_configuration,
None, args.multilib, args.repository, "server")
add_section_mock.assert_has_calls([MockCall("multilib"), MockCall(args.repository)])
_, 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, mocker: MockerFixture) -> None:
def test_configuration_create_devtools_mirror(args: argparse.Namespace, configuration: Configuration,
mocker: MockerFixture) -> None:
"""
must create configuration for the devtools with mirror set explicitly
"""
@ -176,14 +207,15 @@ def test_configuration_create_devtools_mirror(args: argparse.Namespace, mocker:
remove_option_mock = mocker.patch("ahriman.core.configuration.Configuration.remove_option")
set_option_mock = mocker.patch("ahriman.core.configuration.Configuration.set_option")
Setup.configuration_create_devtools(args.build_command, "x86_64", args.from_configuration,
args.mirror, False, args.repository, "server")
_, 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, mocker: MockerFixture) -> None:
def test_configuration_create_devtools_no_multilib(args: argparse.Namespace, configuration: Configuration,
mocker: MockerFixture) -> None:
"""
must create configuration for the devtools without multilib
"""
@ -192,8 +224,8 @@ def test_configuration_create_devtools_no_multilib(args: argparse.Namespace, moc
mocker.patch("ahriman.core.configuration.Configuration.set")
write_mock = mocker.patch("ahriman.core.configuration.Configuration.write")
Setup.configuration_create_devtools(args.build_command, "x86_64", args.from_configuration,
None, False, args.repository, "server")
_, 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))
@ -211,37 +243,38 @@ def test_configuration_create_makepkg(args: argparse.Namespace, repository_paths
Path("home") / ".makepkg.conf", pytest.helpers.anyvar(str, True), encoding="utf8")
def test_configuration_create_sudo(args: argparse.Namespace, repository_paths: RepositoryPaths,
def test_configuration_create_sudo(configuration: Configuration, repository_paths: RepositoryPaths,
mocker: MockerFixture) -> None:
"""
must create sudo configuration
"""
args = _default_args(args)
chmod_text_mock = mocker.patch("pathlib.Path.chmod")
write_text_mock = mocker.patch("pathlib.Path.write_text")
Setup.configuration_create_sudo(repository_paths, args.build_command, "x86_64")
_, 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(args: argparse.Namespace, repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
def test_executable_create(configuration: Configuration, repository_paths: RepositoryPaths,
mocker: MockerFixture) -> None:
"""
must create executable
"""
args = _default_args(args)
chown_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.chown")
symlink_mock = mocker.patch("pathlib.Path.symlink_to")
unlink_mock = mocker.patch("pathlib.Path.unlink")
Setup.executable_create(repository_paths, args.build_command, "x86_64")
chown_mock.assert_called_once_with(Setup.build_command(repository_paths.root, args.build_command, "x86_64"))
_, repository_id = configuration.check_loaded()
Setup.executable_create(repository_paths, repository_id)
chown_mock.assert_called_once_with(Setup.build_command(repository_paths.root, repository_id))
symlink_mock.assert_called_once_with(Setup.ARCHBUILD_COMMAND_PATH)
unlink_mock.assert_called_once_with(missing_ok=True)
def test_disallow_auto_architecture_run() -> None:
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Setup.ALLOW_AUTO_ARCHITECTURE_RUN
assert not Setup.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -32,7 +32,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
application_mock = mocker.patch("code.interact")
Shell.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Shell.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(local=pytest.helpers.anyvar(int))
@ -46,7 +47,8 @@ def test_run_eval(args: argparse.Namespace, configuration: Configuration, reposi
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
application_mock = mocker.patch("code.InteractiveConsole.runcode")
Shell.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Shell.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(args.code)
@ -62,7 +64,15 @@ def test_run_verbose(args: argparse.Namespace, configuration: Configuration, rep
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
application_mock = mocker.patch("code.interact")
Shell.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Shell.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(local=pytest.helpers.anyvar(int))
read_mock.assert_called_once_with(encoding="utf8")
print_mock.assert_called_once_with(verbose=False)
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Shell.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -30,5 +30,6 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
application_mock = mocker.patch("ahriman.application.application.Application.sign")
Sign.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Sign.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with([])

View File

@ -43,7 +43,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
Status.run(args, "x86_64", configuration, report=False)
_, 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, False)
@ -62,7 +63,8 @@ def test_run_empty_exception(args: argparse.Namespace, configuration: Configurat
mocker.patch("ahriman.core.status.client.Client.package_get", return_value=[])
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
Status.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Status.run(args, repository_id, configuration, report=False)
check_mock.assert_called_once_with(True, True)
@ -78,7 +80,8 @@ def test_run_verbose(args: argparse.Namespace, configuration: Configuration, rep
return_value=[(package_ahriman, BuildStatus(BuildStatusEnum.Success))])
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
Status.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Status.run(args, repository_id, configuration, report=False)
print_mock.assert_has_calls([MockCall(verbose=True) for _ in range(2)])
@ -93,7 +96,8 @@ def test_run_with_package_filter(args: argparse.Namespace, configuration: Config
packages_mock = mocker.patch("ahriman.core.status.client.Client.package_get",
return_value=[(package_ahriman, BuildStatus(BuildStatusEnum.Success))])
Status.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Status.run(args, repository_id, configuration, report=False)
packages_mock.assert_called_once_with(package_ahriman.base)
@ -110,7 +114,8 @@ def test_run_by_status(args: argparse.Namespace, configuration: Configuration, r
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
Status.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Status.run(args, repository_id, configuration, report=False)
print_mock.assert_has_calls([MockCall(verbose=False) for _ in range(2)])
@ -123,12 +128,13 @@ def test_imply_with_report(args: argparse.Namespace, configuration: Configuratio
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
load_mock = mocker.patch("ahriman.core.repository.Repository.load")
Status.run(args, "x86_64", configuration, report=False)
load_mock.assert_called_once_with("x86_64", configuration, database, report=True, refresh_pacman_database=0)
_, 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_auto_architecture_run() -> None:
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Status.ALLOW_AUTO_ARCHITECTURE_RUN
assert not Status.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -36,7 +36,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
update_self_mock = mocker.patch("ahriman.core.status.client.Client.status_update")
StatusUpdate.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
StatusUpdate.run(args, repository_id, configuration, report=False)
update_self_mock.assert_called_once_with(args.status)
@ -50,7 +51,8 @@ def test_run_packages(args: argparse.Namespace, configuration: Configuration, re
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
update_mock = mocker.patch("ahriman.core.status.client.Client.package_update")
StatusUpdate.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
StatusUpdate.run(args, repository_id, configuration, report=False)
update_mock.assert_called_once_with(package_ahriman.base, args.status)
@ -65,7 +67,8 @@ def test_run_remove(args: argparse.Namespace, configuration: Configuration, repo
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
update_mock = mocker.patch("ahriman.core.status.client.Client.package_remove")
StatusUpdate.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
StatusUpdate.run(args, repository_id, configuration, report=False)
update_mock.assert_called_once_with(package_ahriman.base)
@ -78,12 +81,13 @@ def test_imply_with_report(args: argparse.Namespace, configuration: Configuratio
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
load_mock = mocker.patch("ahriman.core.repository.Repository.load")
StatusUpdate.run(args, "x86_64", configuration, report=False)
load_mock.assert_called_once_with("x86_64", configuration, database, report=True, refresh_pacman_database=0)
_, 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_auto_architecture_run() -> None:
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not StatusUpdate.ALLOW_AUTO_ARCHITECTURE_RUN
assert not StatusUpdate.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -35,7 +35,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
application_mock = mocker.patch("ahriman.core.tree.Tree.resolve", return_value=[[package_ahriman]])
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
Structure.run(args, "x86_64", configuration, report=False)
_, 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([
@ -45,8 +46,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
])
def test_disallow_auto_architecture_run() -> None:
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Structure.ALLOW_AUTO_ARCHITECTURE_RUN
assert not Structure.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -0,0 +1,42 @@
import argparse
from pathlib import Path
from pytest_mock import MockerFixture
from unittest.mock import call as MockCall
from ahriman.application.handlers import TreeMigrate
from ahriman.core.configuration import Configuration
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.TreeMigrate.tree_move")
_, 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)
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),
])

View File

@ -33,7 +33,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
application_mock = mocker.patch("ahriman.application.application.Application.on_result")
on_start_mock = mocker.patch("ahriman.application.application.Application.on_start")
Triggers.run(args, "x86_64", configuration, report=False)
_, 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()
@ -50,6 +51,7 @@ def test_run_trigger(args: argparse.Namespace, configuration: Configuration, rep
report_mock = mocker.patch("ahriman.core.report.ReportTrigger.on_result")
upload_mock = mocker.patch("ahriman.core.upload.UploadTrigger.on_result")
Triggers.run(args, "x86_64", configuration, report=False)
_, 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()

View File

@ -32,7 +32,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
return_value=["command"])
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
UnsafeCommands.run(args, "x86_64", configuration, report=False)
_, 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)
@ -47,7 +48,8 @@ def test_run_check(args: argparse.Namespace, configuration: Configuration, mocke
return_value=["command"])
check_mock = mocker.patch("ahriman.application.handlers.UnsafeCommands.check_unsafe")
UnsafeCommands.run(args, "x86_64", configuration, report=False)
_, 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))
@ -81,8 +83,8 @@ def test_get_unsafe_commands() -> None:
assert subparser.choices[command].get_default("unsafe")
def test_disallow_auto_architecture_run() -> None:
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not UnsafeCommands.ALLOW_AUTO_ARCHITECTURE_RUN
assert not UnsafeCommands.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -54,7 +54,8 @@ def test_run(args: argparse.Namespace, package_ahriman: Package, configuration:
on_start_mock = mocker.patch("ahriman.application.application.Application.on_start")
print_mock = mocker.patch("ahriman.application.application.Application.print_updates")
Update.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Update.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with([package_ahriman],
Packagers(args.username, {package_ahriman.base: "packager"}),
bump_pkgrel=args.increment)
@ -77,7 +78,8 @@ def test_run_empty_exception(args: argparse.Namespace, configuration: Configurat
mocker.patch("ahriman.application.application.Application.updates", return_value=[])
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
Update.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Update.run(args, repository_id, configuration, report=False)
check_mock.assert_called_once_with(True, True)
@ -95,7 +97,8 @@ def test_run_update_empty_exception(args: argparse.Namespace, package_ahriman: P
mocker.patch("ahriman.application.application.Application.print_updates")
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
Update.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Update.run(args, repository_id, configuration, report=False)
check_mock.assert_has_calls([MockCall(True, False), MockCall(True, True)])
@ -111,7 +114,8 @@ def test_run_dry_run(args: argparse.Namespace, configuration: Configuration, rep
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
updates_mock = mocker.patch("ahriman.application.application.Application.updates")
Update.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Update.run(args, repository_id, configuration, report=False)
updates_mock.assert_called_once_with(args.package, aur=args.aur, local=args.local, manual=args.manual, vcs=args.vcs)
application_mock.assert_not_called()
check_mock.assert_called_once_with(False, pytest.helpers.anyvar(int))

View File

@ -47,7 +47,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, database: S
create_user_mock = mocker.patch("ahriman.application.handlers.Users.user_create", return_value=user)
update_mock = mocker.patch("ahriman.core.database.SQLite.user_update")
Users.run(args, "x86_64", configuration, report=False)
_, 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)
@ -64,7 +65,8 @@ def test_run_empty_salt(args: argparse.Namespace, configuration: Configuration,
create_user_mock = mocker.patch("ahriman.application.handlers.Users.user_create", return_value=user)
update_mock = mocker.patch("ahriman.core.database.SQLite.user_update")
Users.run(args, "x86_64", configuration, report=False)
_, 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)
@ -83,7 +85,8 @@ def test_run_empty_salt_without_password(args: argparse.Namespace, configuration
create_user_mock = mocker.patch("ahriman.application.handlers.Users.user_create", return_value=user)
update_mock = mocker.patch("ahriman.core.database.SQLite.user_update")
Users.run(args, "x86_64", configuration, report=False)
_, 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)
@ -99,7 +102,8 @@ def test_run_list(args: argparse.Namespace, configuration: Configuration, databa
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
list_mock = mocker.patch("ahriman.core.database.SQLite.user_list", return_value=[user])
Users.run(args, "x86_64", configuration, report=False)
_, 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, False)
@ -116,7 +120,8 @@ def test_run_empty_exception(args: argparse.Namespace, configuration: Configurat
mocker.patch("ahriman.core.database.SQLite.user_list", return_value=[])
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
Users.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Users.run(args, repository_id, configuration, report=False)
check_mock.assert_called_once_with(True, True)
@ -130,7 +135,8 @@ def test_run_remove(args: argparse.Namespace, configuration: Configuration, data
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
remove_mock = mocker.patch("ahriman.core.database.SQLite.user_remove")
Users.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Users.run(args, repository_id, configuration, report=False)
remove_mock.assert_called_once_with(args.username)
@ -169,8 +175,8 @@ def test_user_create_getpass_exception(args: argparse.Namespace, mocker: MockerF
Users.user_create(args)
def test_disallow_auto_architecture_run() -> None:
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Users.ALLOW_AUTO_ARCHITECTURE_RUN
assert not Users.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -33,8 +33,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
application_mock = mocker.patch("ahriman.core.configuration.validator.Validator.validate", return_value=False)
Validate.run(args, "x86_64", configuration, report=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)
@ -47,7 +47,8 @@ def test_run_skip(args: argparse.Namespace, configuration: Configuration, mocker
mocker.patch("ahriman.core.configuration.validator.Validator.validate", return_value=True)
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
Validate.run(args, "x86_64", configuration, report=False)
_, repository_id = configuration.check_loaded()
Validate.run(args, repository_id, configuration, report=False)
print_mock.assert_not_called()
@ -55,7 +56,8 @@ def test_schema(configuration: Configuration) -> None:
"""
must generate full schema correctly
"""
schema = Validate.schema("x86_64", configuration)
_, repository_id = configuration.check_loaded()
schema = Validate.schema(repository_id, configuration)
# defaults
assert schema.pop("console")
@ -86,7 +88,9 @@ def test_schema_invalid_trigger(configuration: Configuration) -> None:
"""
configuration.set_option("build", "triggers", "some.invalid.trigger.path.Trigger")
configuration.remove_option("build", "triggers_known")
assert Validate.schema("x86_64", configuration) == CONFIGURATION_SCHEMA
_, repository_id = configuration.check_loaded()
assert Validate.schema(repository_id, configuration) == CONFIGURATION_SCHEMA
def test_schema_erase_required() -> None:
@ -111,8 +115,8 @@ def test_schema_merge() -> None:
assert key in merged["gitremote"]["schema"]
def test_disallow_auto_architecture_run() -> None:
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Validate.ALLOW_AUTO_ARCHITECTURE_RUN
assert not Validate.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -14,7 +14,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
application_mock = mocker.patch("ahriman.application.handlers.Versions.package_dependencies")
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
Versions.run(args, "x86_64", configuration, report=False)
_, 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, separator=" "), MockCall(verbose=False, separator=" ")])
@ -36,3 +37,10 @@ def test_package_dependencies_missing() -> None:
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

View File

@ -41,8 +41,9 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
stop_mock = mocker.patch("ahriman.core.spawn.Spawn.stop")
join_mock = mocker.patch("ahriman.core.spawn.Spawn.join")
Web.run(args, "x86_64", configuration, report=False)
setup_mock.assert_called_once_with("x86_64", configuration, pytest.helpers.anyvar(int))
_, repository_id = configuration.check_loaded()
Web.run(args, repository_id, configuration, report=False)
setup_mock.assert_called_once_with(repository_id, configuration, pytest.helpers.anyvar(int))
run_mock.assert_called_once_with(pytest.helpers.anyvar(int))
start_mock.assert_called_once_with()
stop_mock.assert_called_once_with()
@ -53,33 +54,35 @@ def test_extract_arguments(args: argparse.Namespace, configuration: Configuratio
"""
must extract correct args
"""
_, repository_id = configuration.check_loaded()
expected = [
"--architecture", "x86_64",
"--architecture", repository_id.architecture,
"--repository", repository_id.name,
"--configuration", str(configuration.path),
]
probe = _default_args(args)
assert list(Web.extract_arguments(probe, "x86_64", configuration)) == expected
assert list(Web.extract_arguments(probe, repository_id, configuration)) == expected
probe.force = True
expected.extend(["--force"])
assert list(Web.extract_arguments(probe, "x86_64", configuration)) == expected
assert list(Web.extract_arguments(probe, repository_id, configuration)) == expected
probe.log_handler = LogHandler.Console
expected.extend(["--log-handler", probe.log_handler.value])
assert list(Web.extract_arguments(probe, "x86_64", configuration)) == expected
assert list(Web.extract_arguments(probe, repository_id, configuration)) == expected
probe.quiet = True
expected.extend(["--quiet"])
assert list(Web.extract_arguments(probe, "x86_64", configuration)) == expected
assert list(Web.extract_arguments(probe, repository_id, configuration)) == expected
probe.unsafe = True
expected.extend(["--unsafe"])
assert list(Web.extract_arguments(probe, "x86_64", configuration)) == expected
assert list(Web.extract_arguments(probe, repository_id, configuration)) == expected
configuration.set_option("web", "wait_timeout", "60")
expected.extend(["--wait-timeout", "60"])
assert list(Web.extract_arguments(probe, "x86_64", configuration)) == expected
assert list(Web.extract_arguments(probe, repository_id, configuration)) == expected
def test_extract_arguments_full(parser: argparse.ArgumentParser, configuration: Configuration):
@ -101,8 +104,10 @@ def test_extract_arguments_full(parser: argparse.ArgumentParser, configuration:
value = action.type(value)
setattr(args, action.dest, value)
assert list(Web.extract_arguments(args, "x86_64", configuration)) == [
"--architecture", "x86_64",
_, repository_id = configuration.check_loaded()
assert list(Web.extract_arguments(args, repository_id, configuration)) == [
"--architecture", repository_id.architecture,
"--repository", repository_id.name,
"--configuration", str(configuration.path),
"--force",
"--log-handler", "console",
@ -111,13 +116,6 @@ def test_extract_arguments_full(parser: argparse.ArgumentParser, configuration:
]
def test_disallow_auto_architecture_run() -> None:
"""
must not allow auto architecture run
"""
assert not Web.ALLOW_AUTO_ARCHITECTURE_RUN
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run

File diff suppressed because it is too large Load Diff

View File

@ -18,14 +18,16 @@ def test_path(args: argparse.Namespace, configuration: Configuration) -> None:
"""
must create path variable correctly
"""
assert Lock(args, "x86_64", configuration).path is None
_, repository_id = configuration.check_loaded()
assert Lock(args, repository_id, configuration).path is None
args.lock = Path("/run/ahriman.lock")
assert Lock(args, "x86_64", configuration).path == Path("/run/ahriman_x86_64.lock")
assert Lock(args, repository_id, configuration).path == Path("/run/ahriman_aur-clone_x86_64.lock")
with pytest.raises(ValueError):
args.lock = Path("/")
Lock(args, "x86_64", configuration).path # special case
Lock(args, repository_id, configuration).path # special case
def test_check_version(lock: Lock, mocker: MockerFixture) -> None:

View File

@ -19,7 +19,9 @@ from ahriman.models.build_status import BuildStatus, BuildStatusEnum
from ahriman.models.package import Package
from ahriman.models.package_description import PackageDescription
from ahriman.models.package_source import PackageSource
from ahriman.models.pacman_synchronization import PacmanSynchronization
from ahriman.models.remote_source import RemoteSource
from ahriman.models.repository_id import RepositoryId
from ahriman.models.repository_paths import RepositoryPaths
from ahriman.models.result import Result
from ahriman.models.user import User
@ -243,18 +245,19 @@ def auth(configuration: Configuration) -> Auth:
@pytest.fixture
def configuration(resource_path_root: Path) -> Configuration:
def configuration(repository_id: RepositoryId, resource_path_root: Path) -> Configuration:
"""
configuration fixture
Args:
repository_id(RepositoryId): repository identifier fixture
resource_path_root(Path): resource path root directory
Returns:
Configuration: configuration test instance
"""
path = resource_path_root / "core" / "ahriman.ini"
return Configuration.from_path(path=path, architecture="x86_64")
return Configuration.from_path(path, repository_id)
@pytest.fixture
@ -434,7 +437,8 @@ def pacman(configuration: Configuration) -> Pacman:
Returns:
Pacman: pacman wrapper test instance
"""
return Pacman("x86_64", configuration, refresh_database=0)
_, repository_id = configuration.check_loaded()
return Pacman(repository_id, configuration, refresh_database=PacmanSynchronization.Disabled)
@pytest.fixture
@ -481,7 +485,19 @@ def repository(configuration: Configuration, database: SQLite, mocker: MockerFix
Repository: repository test instance
"""
mocker.patch("ahriman.core.repository.Repository._set_context")
return Repository.load("x86_64", configuration, database, report=False)
_, repository_id = configuration.check_loaded()
return Repository.load(repository_id, configuration, database, report=False)
@pytest.fixture
def repository_id() -> RepositoryId:
"""
fixture for repository identifier
Returns:
RepositoryId: repository identifier test instance
"""
return RepositoryId("x86_64", "aur-clone")
@pytest.fixture
@ -525,7 +541,12 @@ def spawner(configuration: Configuration) -> Spawn:
Returns:
Spawn: spawner fixture
"""
return Spawn(MagicMock(), "x86_64", ["--architecture", "x86_64", "--configuration", str(configuration.path)])
_, repository_id = configuration.check_loaded()
return Spawn(MagicMock(), repository_id, [
"--architecture", "x86_64",
"--repository", repository_id.name,
"--configuration", str(configuration.path),
])
@pytest.fixture
@ -554,4 +575,5 @@ def watcher(configuration: Configuration, database: SQLite, repository: Reposito
Watcher: package status watcher test instance
"""
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
return Watcher("x86_64", configuration, database)
_, repository_id = configuration.check_loaded()
return Watcher(repository_id, configuration, database)

View File

@ -19,12 +19,13 @@ def test_init_with_local_cache(configuration: Configuration, mocker: MockerFixtu
mocker.patch("ahriman.core.alpm.pacman.Pacman.database_copy")
sync_mock = mocker.patch("ahriman.core.alpm.pacman.Pacman.database_sync")
configuration.set_option("alpm", "use_ahriman_cache", "yes")
_, repository_id = configuration.check_loaded()
# pyalpm.Handle is trying to reach the directory we've asked, thus we need to patch it a bit
with TemporaryDirectory(ignore_cleanup_errors=True) as pacman_root:
mocker.patch.object(RepositoryPaths, "pacman", Path(pacman_root))
# during the creation pyalpm.Handle will create also version file which we would like to remove later
pacman = Pacman("x86_64", configuration, refresh_database=PacmanSynchronization.Enabled)
pacman = Pacman(repository_id, configuration, refresh_database=PacmanSynchronization.Enabled)
assert pacman.handle
sync_mock.assert_called_once_with(pytest.helpers.anyvar(int), force=False)
@ -36,12 +37,13 @@ def test_init_with_local_cache_forced(configuration: Configuration, mocker: Mock
mocker.patch("ahriman.core.alpm.pacman.Pacman.database_copy")
sync_mock = mocker.patch("ahriman.core.alpm.pacman.Pacman.database_sync")
configuration.set_option("alpm", "use_ahriman_cache", "yes")
_, repository_id = configuration.check_loaded()
# pyalpm.Handle is trying to reach the directory we've asked, thus we need to patch it a bit
with TemporaryDirectory(ignore_cleanup_errors=True) as pacman_root:
mocker.patch.object(RepositoryPaths, "pacman", Path(pacman_root))
# during the creation pyalpm.Handle will create also version file which we would like to remove later
pacman = Pacman("x86_64", configuration, refresh_database=PacmanSynchronization.Force)
pacman = Pacman(repository_id, configuration, refresh_database=PacmanSynchronization.Force)
assert pacman.handle
sync_mock.assert_called_once_with(pytest.helpers.anyvar(int), force=True)
@ -56,10 +58,12 @@ def test_database_copy(pacman: Pacman, repository_paths: RepositoryPaths, mocker
mocker.patch("pathlib.Path.is_dir", return_value=True)
# root database exists, local database does not
mocker.patch("pathlib.Path.is_file", autospec=True, side_effect=lambda p: p.is_relative_to(path))
mkdir_mock = mocker.patch("pathlib.Path.mkdir")
copy_mock = mocker.patch("shutil.copy")
chown_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.chown")
pacman.database_copy(pacman.handle, database, path, repository_paths, use_ahriman_cache=True)
mkdir_mock.assert_called_once_with(mode=0o755, exist_ok=True)
copy_mock.assert_called_once_with(path / "sync" / "core.db", dst_path)
chown_mock.assert_called_once_with(dst_path)
@ -128,8 +132,8 @@ def test_database_init(pacman: Pacman, configuration: Configuration) -> None:
must init database with settings
"""
mirror = configuration.get("alpm", "mirror")
database = pacman.database_init(pacman.handle, "test", mirror, "x86_64")
assert len(database.servers) == 1
database = pacman.database_init(pacman.handle, "testing", mirror, "x86_64")
assert database.servers == ["https://geo.mirror.pkgbuild.com/testing/os/x86_64"]
def test_database_sync(pacman: Pacman) -> None:

View File

@ -177,7 +177,7 @@ def test_load(package_ahriman: Package, repository_paths: RepositoryPaths, mocke
Sources.load(path, package_ahriman, [patch], repository_paths)
fetch_mock.assert_called_once_with(path, package_ahriman.remote)
patch_mock.assert_called_once_with(path, patch)
architectures_mock.assert_called_once_with(path, repository_paths.architecture)
architectures_mock.assert_called_once_with(path, repository_paths.repository_id.architecture)
def test_load_no_patch(package_ahriman: Package, repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:

View File

@ -7,9 +7,17 @@ from unittest.mock import call as MockCall
from ahriman.core.configuration import Configuration
from ahriman.core.exceptions import InitializeError
from ahriman.models.repository_id import RepositoryId
from ahriman.models.repository_paths import RepositoryPaths
def test_architecture(configuration: Configuration) -> None:
"""
must return valid repository architecture
"""
assert configuration.architecture == "x86_64"
def test_repository_name(configuration: Configuration) -> None:
"""
must return valid repository name
@ -24,7 +32,7 @@ def test_repository_paths(configuration: Configuration, repository_paths: Reposi
assert configuration.repository_paths == repository_paths
def test_from_path(mocker: MockerFixture) -> None:
def test_from_path(repository_id: RepositoryId, mocker: MockerFixture) -> None:
"""
must load configuration
"""
@ -33,13 +41,13 @@ def test_from_path(mocker: MockerFixture) -> None:
load_includes_mock = mocker.patch("ahriman.core.configuration.Configuration.load_includes")
path = Path("path")
configuration = Configuration.from_path(path, "x86_64")
configuration = Configuration.from_path(path, repository_id)
assert configuration.path == path
read_mock.assert_called_once_with(path)
load_includes_mock.assert_called_once_with()
def test_from_path_file_missing(mocker: MockerFixture) -> None:
def test_from_path_file_missing(repository_id: RepositoryId, mocker: MockerFixture) -> None:
"""
must load configuration based on package files
"""
@ -47,17 +55,40 @@ def test_from_path_file_missing(mocker: MockerFixture) -> None:
mocker.patch("ahriman.core.configuration.Configuration.load_includes")
read_mock = mocker.patch("ahriman.core.configuration.Configuration.read")
configuration = Configuration.from_path(Path("path"), "x86_64")
configuration = Configuration.from_path(Path("path"), repository_id)
read_mock.assert_called_once_with(configuration.SYSTEM_CONFIGURATION_PATH)
def test_override_sections(repository_id: RepositoryId) -> None:
"""
must correctly generate override section names
"""
assert Configuration.override_sections("build", repository_id) == [
"build:x86_64",
"build:aur-clone",
"build:aur-clone:x86_64",
]
def test_section_name(configuration: Configuration) -> None:
"""
must return architecture specific group
"""
assert configuration.section_name("build") == "build"
assert configuration.section_name("build", None) == "build"
assert configuration.section_name("build", "x86_64") == "build:x86_64"
assert configuration.section_name("build", "aur-clone", "x86_64") == "build:aur-clone:x86_64"
assert configuration.section_name("build", "aur-clone", None) == "build:aur-clone"
assert configuration.section_name("build", None, "x86_64") == "build:x86_64"
def test_check_loaded(configuration: Configuration) -> None:
"""
must return valid path and architecture
"""
path, architecture = configuration.check_loaded()
path, repository_id = configuration.check_loaded()
assert path == configuration.path
assert architecture == configuration.architecture
assert repository_id == configuration.repository_id
def test_check_loaded_path(configuration: Configuration) -> None:
@ -73,7 +104,7 @@ def test_check_loaded_architecture(configuration: Configuration) -> None:
"""
must raise exception if architecture is none
"""
configuration.architecture = None
configuration.repository_id = None
with pytest.raises(InitializeError):
configuration.check_loaded()
@ -89,9 +120,9 @@ def test_dump_architecture_specific(configuration: Configuration) -> None:
"""
dump must contain architecture specific settings
"""
section = configuration.section_name("build", "x86_64")
section = configuration.section_name("build", configuration.architecture)
configuration.set_option(section, "archbuild_flags", "hello flag")
configuration.merge_sections("x86_64")
configuration.merge_sections(configuration.repository_id)
dump = configuration.dump()
assert dump
@ -100,13 +131,6 @@ def test_dump_architecture_specific(configuration: Configuration) -> None:
assert dump["build"]["archbuild_flags"] == "hello flag"
def test_section_name(configuration: Configuration) -> None:
"""
must return architecture specific group
"""
assert configuration.section_name("build", "x86_64") == "build:x86_64"
def test_getlist(configuration: Configuration) -> None:
"""
must return list of string correctly
@ -209,7 +233,7 @@ def test_gettype(configuration: Configuration) -> None:
"""
must extract type from variable
"""
section, provider = configuration.gettype("customs3", "x86_64")
section, provider = configuration.gettype("customs3", configuration.repository_id)
assert section == "customs3"
assert provider == "s3"
@ -218,7 +242,7 @@ def test_gettype_with_fallback(configuration: Configuration) -> None:
"""
must return same provider name as in fallback
"""
section, provider = configuration.gettype("rsync", "x86_64", fallback="abracadabra")
section, provider = configuration.gettype("rsync", configuration.repository_id, fallback="abracadabra")
assert section == "rsync"
assert provider == "abracadabra"
@ -227,7 +251,7 @@ def test_gettype_from_section(configuration: Configuration) -> None:
"""
must extract type from section name
"""
section, provider = configuration.gettype("rsync", "x86_64")
section, provider = configuration.gettype("rsync", configuration.repository_id)
assert section == "rsync"
assert provider == "rsync"
@ -236,7 +260,7 @@ def test_gettype_from_section_with_architecture(configuration: Configuration) ->
"""
must extract type from section name with architecture
"""
section, provider = configuration.gettype("github", "x86_64")
section, provider = configuration.gettype("github", configuration.repository_id)
assert section == "github:x86_64"
assert provider == "github"
@ -248,7 +272,7 @@ def test_gettype_from_section_no_section(configuration: Configuration) -> None:
# technically rsync:x86_64 is valid section
# but in current configuration it must be considered as missing section
with pytest.raises(configparser.NoSectionError):
configuration.gettype("rsync:x86_64", "x86_64")
configuration.gettype("rsync:x86_64", configuration.repository_id)
def test_load_includes_missing(configuration: Configuration) -> None:
@ -279,14 +303,44 @@ def test_merge_sections_missing(configuration: Configuration) -> None:
"""
must merge create section if not exists
"""
section = configuration.section_name("build", "x86_64")
section = configuration.section_name("build", configuration.architecture)
configuration.remove_section("build")
configuration.set_option(section, "key", "value")
configuration.merge_sections("x86_64")
configuration.merge_sections(configuration.repository_id)
assert configuration.get("build", "key") == "value"
def test_merge_sections_priority(configuration: Configuration) -> None:
"""
must merge sections in valid order
"""
empty = "build"
arch = configuration.section_name(empty, configuration.architecture)
repo = configuration.section_name(empty, configuration.repository_name)
repo_arch = configuration.section_name(empty, configuration.repository_name, configuration.architecture)
configuration.set_option(empty, "key1", "key1_value1")
configuration.set_option(arch, "key1", "key1_value2")
configuration.set_option(repo, "key1", "key1_value3")
configuration.set_option(repo_arch, "key1", "key1_value4")
configuration.set_option(empty, "key2", "key2_value1")
configuration.set_option(arch, "key2", "key2_value2")
configuration.set_option(repo, "key2", "key2_value3")
configuration.set_option(empty, "key3", "key3_value1")
configuration.set_option(arch, "key3", "key3_value2")
configuration.set_option(empty, "key4", "key4_value1")
configuration.merge_sections(configuration.repository_id)
assert configuration.get("build", "key1") == "key1_value4"
assert configuration.get("build", "key2") == "key2_value3"
assert configuration.get("build", "key3") == "key3_value2"
assert configuration.get("build", "key4") == "key4_value1"
def test_reload(configuration: Configuration, mocker: MockerFixture) -> None:
"""
must reload configuration
@ -296,7 +350,7 @@ def test_reload(configuration: Configuration, mocker: MockerFixture) -> None:
configuration.reload()
load_mock.assert_called_once_with(configuration.path)
merge_mock.assert_called_once_with(configuration.architecture)
merge_mock.assert_called_once_with(configuration.repository_id)
def test_reload_clear(configuration: Configuration, mocker: MockerFixture) -> None:
@ -314,7 +368,7 @@ def test_reload_no_architecture(configuration: Configuration) -> None:
"""
must raise exception on reload if no architecture set
"""
configuration.architecture = None
configuration.repository_id = None
with pytest.raises(InitializeError):
configuration.reload()

View File

@ -2,10 +2,12 @@ import pytest
from sqlite3 import Connection
from pytest_mock import MockerFixture
from unittest.mock import call as MockCall
from ahriman.core.configuration import Configuration
from ahriman.core.database.migrations.m001_package_source import migrate_data, migrate_package_remotes, steps
from ahriman.models.package import Package
from ahriman.models.package_source import PackageSource
from ahriman.models.repository_paths import RepositoryPaths
@ -30,13 +32,18 @@ def test_migrate_package_remotes(package_ahriman: Package, connection: Connectio
"""
must put package remotes to database
"""
mocker.patch(
"ahriman.core.database.operations.PackageOperations._packages_get_select_package_bases",
return_value={package_ahriman.base: package_ahriman})
connection.execute.return_value = [{
"package_base": package_ahriman.base,
"version": package_ahriman.version,
"source": PackageSource.AUR,
}]
mocker.patch("pathlib.Path.exists", return_value=False)
migrate_package_remotes(connection, repository_paths)
connection.execute.assert_called_once_with(pytest.helpers.anyvar(str, strict=True), pytest.helpers.anyvar(int))
connection.execute.assert_has_calls([
MockCall(pytest.helpers.anyvar(str, strict=True)),
MockCall(pytest.helpers.anyvar(str, strict=True), pytest.helpers.anyvar(int)),
])
def test_migrate_package_remotes_has_local(package_ahriman: Package, connection: Connection,
@ -44,13 +51,15 @@ def test_migrate_package_remotes_has_local(package_ahriman: Package, connection:
"""
must skip processing for packages which have local cache
"""
mocker.patch(
"ahriman.core.database.operations.PackageOperations._packages_get_select_package_bases",
return_value={package_ahriman.base: package_ahriman})
connection.execute.return_value = [{
"package_base": package_ahriman.base,
"version": package_ahriman.version,
"source": PackageSource.AUR,
}]
mocker.patch("pathlib.Path.exists", return_value=True)
migrate_package_remotes(connection, repository_paths)
connection.execute.assert_not_called()
connection.execute.assert_called_once_with(pytest.helpers.anyvar(str, strict=True))
def test_migrate_package_remotes_vcs(package_ahriman: Package, connection: Connection,
@ -58,11 +67,16 @@ def test_migrate_package_remotes_vcs(package_ahriman: Package, connection: Conne
"""
must process VCS packages with local cache
"""
mocker.patch(
"ahriman.core.database.operations.PackageOperations._packages_get_select_package_bases",
return_value={package_ahriman.base: package_ahriman})
connection.execute.return_value = [{
"package_base": package_ahriman.base,
"version": package_ahriman.version,
"source": PackageSource.AUR,
}]
mocker.patch("pathlib.Path.exists", return_value=True)
mocker.patch.object(Package, "is_vcs", True)
migrate_package_remotes(connection, repository_paths)
connection.execute.assert_called_once_with(pytest.helpers.anyvar(str, strict=True), pytest.helpers.anyvar(int))
connection.execute.assert_has_calls([
MockCall(pytest.helpers.anyvar(str, strict=True)),
MockCall(pytest.helpers.anyvar(str, strict=True), pytest.helpers.anyvar(int)),
])

View File

@ -0,0 +1,39 @@
import pytest
from pytest_mock import MockerFixture
from sqlite3 import Connection
from unittest.mock import call as MockCall
from ahriman.core.configuration import Configuration
from ahriman.core.database.migrations.m011_repository_name import migrate_data, migrate_package_repository, steps
def test_migration_check_depends() -> None:
"""
migration must not be empty
"""
assert steps
def test_migrate_data(connection: Connection, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must perform data migration
"""
repository_mock = mocker.patch("ahriman.core.database.migrations.m011_repository_name.migrate_package_repository")
migrate_data(connection, configuration)
repository_mock.assert_called_once_with(connection, configuration)
def test_migrate_package_repository(connection: Connection, configuration: Configuration) -> None:
"""
must correctly set repository and architecture
"""
migrate_package_repository(connection, configuration)
connection.execute.assert_has_calls([
MockCall(pytest.helpers.anyvar(str, strict=True), {"repository": configuration.repository_id.id}),
MockCall(pytest.helpers.anyvar(str, strict=True), {"repository": configuration.repository_id.id}),
MockCall(pytest.helpers.anyvar(str, strict=True), {"repository": configuration.repository_id.id}),
MockCall(pytest.helpers.anyvar(str, strict=True), {"repository": configuration.repository_id.id}),
MockCall(pytest.helpers.anyvar(str, strict=True), {"repository": configuration.repository_id.id}),
])

View File

@ -1,5 +1,6 @@
from ahriman.core.database import SQLite
from ahriman.models.package import Package
from ahriman.models.repository_id import RepositoryId
def test_build_queue_insert_clear(database: SQLite, package_ahriman: Package, package_python_schedule: Package) -> None:
@ -13,6 +14,19 @@ def test_build_queue_insert_clear(database: SQLite, package_ahriman: Package, pa
assert not database.build_queue_get()
def test_build_queue_insert_clear_multi(database: SQLite, package_ahriman: Package) -> None:
"""
must clear all packages from queue for specific repository
"""
database.build_queue_insert(package_ahriman)
database.repository_id = RepositoryId("i686", database.repository_id.name)
database.build_queue_insert(package_ahriman)
database.build_queue_clear(None)
database.repository_id = RepositoryId("x86_64", database.repository_id.name)
assert database.build_queue_get() == [package_ahriman]
def test_build_queue_insert_clear_specific(database: SQLite, package_ahriman: Package,
package_python_schedule: Package) -> None:
"""
@ -43,3 +57,30 @@ def test_build_queue_insert(database: SQLite, package_ahriman: Package) -> None:
package_ahriman.version = "42"
database.build_queue_insert(package_ahriman)
assert database.build_queue_get() == [package_ahriman]
def test_build_queue_insert_multi(database: SQLite, package_ahriman: Package) -> None:
"""
must update build queue in the database for multiple architectures and repositories
"""
package_ahriman.version = "1"
database.build_queue_insert(package_ahriman)
assert database.build_queue_get() == [package_ahriman]
package_ahriman.version = "2"
database.repository_id = RepositoryId("i686", database.repository_id.name)
database.build_queue_insert(package_ahriman)
assert database.build_queue_get() == [package_ahriman]
package_ahriman.version = "1"
database.repository_id = RepositoryId("x86_64", database.repository_id.name)
assert database.build_queue_get() == [package_ahriman]
package_ahriman.version = "3"
database.repository_id = RepositoryId(database.repository_id.architecture, "repo")
database.build_queue_insert(package_ahriman)
assert database.build_queue_get() == [package_ahriman]
package_ahriman.version = "1"
database.repository_id = RepositoryId(database.repository_id.architecture, "aur-clone")
assert database.build_queue_get() == [package_ahriman]

View File

@ -1,12 +1,13 @@
from ahriman.core.database import SQLite
from ahriman.models.log_record_id import LogRecordId
from ahriman.models.package import Package
from ahriman.models.repository_id import RepositoryId
def test_logs_insert_remove_process(database: SQLite, package_ahriman: Package,
def test_logs_insert_remove_version(database: SQLite, package_ahriman: Package,
package_python_schedule: Package) -> None:
"""
must clear process specific package logs
must clear version specific package logs
"""
database.logs_insert(LogRecordId(package_ahriman.base, "1"), 42.0, "message 1")
database.logs_insert(LogRecordId(package_ahriman.base, "2"), 43.0, "message 2")
@ -17,6 +18,20 @@ def test_logs_insert_remove_process(database: SQLite, package_ahriman: Package,
assert database.logs_get(package_python_schedule.base) == [(42.0, "message 3")]
def test_logs_insert_remove_multi(database: SQLite, package_ahriman: Package) -> None:
"""
must clear logs for specified repository
"""
database.logs_insert(LogRecordId(package_ahriman.base, "1"), 42.0, "message 1")
database.repository_id = RepositoryId("i686", database.repository_id.name)
database.logs_insert(LogRecordId(package_ahriman.base, "1"), 43.0, "message 2")
database.logs_remove(package_ahriman.base, None)
assert not database.logs_get(package_ahriman.base)
database.repository_id = RepositoryId("x86_64", database.repository_id.name)
assert database.logs_get(package_ahriman.base) == [(42.0, "message 1")]
def test_logs_insert_remove_full(database: SQLite, package_ahriman: Package, package_python_schedule: Package) -> None:
"""
must clear full package logs
@ -46,3 +61,16 @@ def test_logs_insert_get_pagination(database: SQLite, package_ahriman: Package)
database.logs_insert(LogRecordId(package_ahriman.base, "1"), 42.0, "message 1")
database.logs_insert(LogRecordId(package_ahriman.base, "1"), 43.0, "message 2")
assert database.logs_get(package_ahriman.base, 1, 1) == [(43.0, "message 2")]
def test_logs_insert_get_multi(database: SQLite, package_ahriman: Package) -> None:
"""
must insert and get package logs for multiple repositories
"""
database.logs_insert(LogRecordId(package_ahriman.base, "1"), 42.0, "message 1")
database.repository_id = RepositoryId("i686", database.repository_id.name)
database.logs_insert(LogRecordId(package_ahriman.base, "1"), 43.0, "message 2")
assert database.logs_get(package_ahriman.base) == [(43.0, "message 2")]
database.repository_id = RepositoryId("x86_64", database.repository_id.name)
assert database.logs_get(package_ahriman.base) == [(42.0, "message 1")]

View File

@ -16,9 +16,13 @@ def test_package_remove_package_base(database: SQLite, connection: Connection) -
must remove package base
"""
database._package_remove_package_base(connection, "package")
args = {
"package_base": "package",
"repository": database.repository_id.id,
}
connection.execute.assert_has_calls([
MockCall(pytest.helpers.anyvar(str, strict=True), {"package_base": "package"}),
MockCall(pytest.helpers.anyvar(str, strict=True), {"package_base": "package"}),
MockCall(pytest.helpers.anyvar(str, strict=True), args),
MockCall(pytest.helpers.anyvar(str, strict=True), args),
])
@ -28,7 +32,10 @@ def test_package_remove_packages(database: SQLite, connection: Connection, packa
"""
database._package_remove_packages(connection, package_ahriman.base, package_ahriman.packages.keys())
connection.execute.assert_called_once_with(
pytest.helpers.anyvar(str, strict=True), {"package_base": package_ahriman.base})
pytest.helpers.anyvar(str, strict=True), {
"package_base": package_ahriman.base,
"repository": database.repository_id.id,
})
connection.executemany.assert_called_once_with(pytest.helpers.anyvar(str, strict=True), [])

View File

@ -22,7 +22,7 @@ def test_patches_list(database: SQLite, package_ahriman: Package, package_python
database.patches_insert(package_ahriman.base, PkgbuildPatch(None, "patch1"))
database.patches_insert(package_ahriman.base, PkgbuildPatch("key", "patch3"))
database.patches_insert(package_python_schedule.base, PkgbuildPatch(None, "patch2"))
assert database.patches_list(None, []) == {
assert database.patches_list(None, None) == {
package_ahriman.base: [PkgbuildPatch(None, "patch1"), PkgbuildPatch("key", "patch3")],
package_python_schedule.base: [PkgbuildPatch(None, "patch2")],
}
@ -35,8 +35,8 @@ def test_patches_list_filter(database: SQLite, package_ahriman: Package, package
database.patches_insert(package_ahriman.base, PkgbuildPatch(None, "patch1"))
database.patches_insert(package_python_schedule.base, PkgbuildPatch(None, "patch2"))
assert database.patches_list(package_ahriman.base, []) == {package_ahriman.base: [PkgbuildPatch(None, "patch1")]}
assert database.patches_list(package_python_schedule.base, []) == {
assert database.patches_list(package_ahriman.base, None) == {package_ahriman.base: [PkgbuildPatch(None, "patch1")]}
assert database.patches_list(package_python_schedule.base, None) == {
package_python_schedule.base: [PkgbuildPatch(None, "patch2")],
}
@ -50,7 +50,7 @@ def test_patches_list_filter_by_variable(database: SQLite, package_ahriman: Pack
database.patches_insert(package_ahriman.base, PkgbuildPatch("key", "patch2"))
database.patches_insert(package_python_schedule.base, PkgbuildPatch(None, "patch3"))
assert database.patches_list(None, []) == {
assert database.patches_list(None, None) == {
package_ahriman.base: [PkgbuildPatch(None, "patch1"), PkgbuildPatch("key", "patch2")],
package_python_schedule.base: [PkgbuildPatch(None, "patch3")],
}
@ -65,7 +65,7 @@ def test_patches_insert_remove(database: SQLite, package_ahriman: Package, packa
"""
database.patches_insert(package_ahriman.base, PkgbuildPatch(None, "patch1"))
database.patches_insert(package_python_schedule.base, PkgbuildPatch(None, "patch2"))
database.patches_remove(package_ahriman.base, [])
database.patches_remove(package_ahriman.base, None)
assert database.patches_get(package_ahriman.base) == []
assert database.patches_get(package_python_schedule.base) == [PkgbuildPatch(None, "patch2")]

View File

@ -16,7 +16,8 @@ def test_repo_clone(configuration: Configuration, mocker: MockerFixture) -> None
"""
fetch_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.fetch")
copy_mock = mocker.patch("ahriman.core.gitremote.remote_pull.RemotePull.repo_copy")
runner = RemotePull(configuration, "x86_64", "gitremote")
_, repository_id = configuration.check_loaded()
runner = RemotePull(repository_id, configuration, "gitremote")
runner.repo_clone()
fetch_mock.assert_called_once_with(pytest.helpers.anyvar(int), runner.remote_source)
@ -32,7 +33,8 @@ def test_package_copy(configuration: Configuration, package_ahriman: Package, mo
ignore_patterns_mock = mocker.patch("shutil.ignore_patterns", return_value=patterns)
copytree_mock = mocker.patch("shutil.copytree")
init_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.init")
runner = RemotePull(configuration, "x86_64", "gitremote")
_, repository_id = configuration.check_loaded()
runner = RemotePull(repository_id, configuration, "gitremote")
local = Path("local")
runner.package_copy(local / "PKGBUILD")
@ -57,7 +59,8 @@ def test_repo_copy(configuration: Configuration, mocker: MockerFixture) -> None:
local / "package3" / ".SRCINFO",
])
copy_mock = mocker.patch("ahriman.core.gitremote.remote_pull.RemotePull.package_copy")
runner = RemotePull(configuration, "x86_64", "gitremote")
_, repository_id = configuration.check_loaded()
runner = RemotePull(repository_id, configuration, "gitremote")
runner.repo_copy(local)
copy_mock.assert_has_calls([
@ -71,7 +74,8 @@ def test_run(configuration: Configuration, mocker: MockerFixture) -> None:
must clone repo on run
"""
clone_mock = mocker.patch("ahriman.core.gitremote.remote_pull.RemotePull.repo_clone")
runner = RemotePull(configuration, "x86_64", "gitremote")
_, repository_id = configuration.check_loaded()
runner = RemotePull(repository_id, configuration, "gitremote")
runner.run()
clone_mock.assert_called_once_with()
@ -82,7 +86,8 @@ def test_run_failed(configuration: Configuration, mocker: MockerFixture) -> None
must reraise exception on error occurred
"""
mocker.patch("ahriman.core.gitremote.remote_pull.RemotePull.repo_clone", side_effect=Exception())
runner = RemotePull(configuration, "x86_64", "gitremote")
_, repository_id = configuration.check_loaded()
runner = RemotePull(repository_id, configuration, "gitremote")
with pytest.raises(GitRemoteError):
runner.run()

View File

@ -20,7 +20,8 @@ def test_on_start(configuration: Configuration, mocker: MockerFixture) -> None:
must clone repo on start
"""
run_mock = mocker.patch("ahriman.core.gitremote.remote_pull.RemotePull.run")
trigger = RemotePullTrigger("x86_64", configuration)
_, repository_id = configuration.check_loaded()
trigger = RemotePullTrigger(repository_id, configuration)
trigger.on_start()
run_mock.assert_called_once_with()

View File

@ -26,7 +26,8 @@ def test_on_result(configuration: Configuration, result: Result, package_ahriman
"""
database_mock = mocker.patch("ahriman.core._Context.get", return_value=database)
run_mock = mocker.patch("ahriman.core.gitremote.remote_push.RemotePush.run")
trigger = RemotePushTrigger("x86_64", configuration)
_, repository_id = configuration.check_loaded()
trigger = RemotePushTrigger(repository_id, configuration)
trigger.on_result(result, [package_ahriman])
database_mock.assert_called_once_with(ContextKey("database", SQLite))

View File

@ -22,7 +22,7 @@ def test_init_auth(configuration: Configuration) -> None:
configuration.set_option("web", "username", "username")
configuration.set_option("web", "password", "password")
assert SyncHttpClient("web", configuration).auth == ("username", "password")
assert SyncHttpClient(configuration, "web").auth == ("username", "password")
assert SyncHttpClient(configuration=configuration).auth is None

View File

@ -7,7 +7,7 @@ from pytest_mock import MockerFixture
from systemd.journal import JournalHandler
from ahriman.core.configuration import Configuration
from ahriman.core.log import Log
from ahriman.core.log.log_loader import LogLoader
from ahriman.models.log_handler import LogHandler
@ -15,14 +15,14 @@ def test_handler() -> None:
"""
must extract journald handler if available
"""
assert Log.handler(None) == LogHandler.Journald
assert LogLoader.handler(None) == LogHandler.Journald
def test_handler_selected() -> None:
"""
must return selected log handler
"""
assert Log.handler(LogHandler.Console) == LogHandler.Console
assert LogLoader.handler(LogHandler.Console) == LogHandler.Console
def test_handler_syslog(mocker: MockerFixture) -> None:
@ -31,7 +31,7 @@ def test_handler_syslog(mocker: MockerFixture) -> None:
"""
mocker.patch("pathlib.Path.exists", return_value=True)
mocker.patch.dict(sys.modules, {"systemd.journal": None})
assert Log.handler(None) == LogHandler.Syslog
assert LogLoader.handler(None) == LogHandler.Syslog
def test_handler_console(mocker: MockerFixture) -> None:
@ -40,17 +40,17 @@ def test_handler_console(mocker: MockerFixture) -> None:
"""
mocker.patch("pathlib.Path.exists", return_value=False)
mocker.patch.dict(sys.modules, {"systemd.journal": None})
assert Log.handler(None) == LogHandler.Console
assert LogLoader.handler(None) == LogHandler.Console
def test_load(configuration: Configuration, mocker: MockerFixture) -> None:
"""
must load logging
"""
logging_mock = mocker.patch("ahriman.core.log.log.fileConfig", side_effect=fileConfig)
logging_mock = mocker.patch("ahriman.core.log.log_loader.fileConfig", side_effect=fileConfig)
http_log_mock = mocker.patch("ahriman.core.log.http_log_handler.HttpLogHandler.load")
Log.load(configuration, LogHandler.Journald, quiet=False, report=False)
LogLoader.load(configuration, LogHandler.Journald, quiet=False, report=False)
logging_mock.assert_called_once_with(pytest.helpers.anyvar(int), disable_existing_loggers=True)
http_log_mock.assert_called_once_with(configuration, report=False)
assert all(isinstance(handler, JournalHandler) for handler in logging.getLogger().handlers)
@ -60,8 +60,8 @@ def test_load_fallback(configuration: Configuration, mocker: MockerFixture) -> N
"""
must fall back to stderr without errors
"""
mocker.patch("ahriman.core.log.log.fileConfig", side_effect=PermissionError())
Log.load(configuration, LogHandler.Journald, quiet=False, report=False)
mocker.patch("ahriman.core.log.log_loader.fileConfig", side_effect=PermissionError())
LogLoader.load(configuration, LogHandler.Journald, quiet=False, report=False)
def test_load_quiet(configuration: Configuration, mocker: MockerFixture) -> None:
@ -69,5 +69,5 @@ def test_load_quiet(configuration: Configuration, mocker: MockerFixture) -> None
must disable logging in case if quiet flag set
"""
disable_mock = mocker.patch("logging.disable")
Log.load(configuration, LogHandler.Journald, quiet=True, report=False)
LogLoader.load(configuration, LogHandler.Journald, quiet=True, report=False)
disable_mock.assert_called_once_with(logging.WARNING)

View File

@ -1,7 +1,24 @@
import pytest
from ahriman.core.configuration import Configuration
from ahriman.core.report.email import Email
from ahriman.core.report.remote_call import RemoteCall
from ahriman.core.report.telegram import Telegram
@pytest.fixture
def email(configuration: Configuration) -> Email:
"""
fixture for email trigger
Args:
configuration(Configuration): configuration fixture
Returns:
RemoteCall: email trigger test instance
"""
_, repository_id = configuration.check_loaded()
return Email(repository_id, configuration, "email")
@pytest.fixture
@ -17,4 +34,20 @@ def remote_call(configuration: Configuration) -> RemoteCall:
"""
configuration.set_option("web", "host", "localhost")
configuration.set_option("web", "port", "8080")
return RemoteCall("x86_64", configuration, "remote-call")
_, repository_id = configuration.check_loaded()
return RemoteCall(repository_id, configuration, "remote-call")
@pytest.fixture
def telegram(configuration: Configuration) -> Telegram:
"""
fixture for telegram trigger
Args:
configuration(Configuration): configuration fixture
Returns:
RemoteCall: telegram trigger test instance
"""
_, repository_id = configuration.check_loaded()
return Telegram(repository_id, configuration, "telegram")

View File

@ -14,7 +14,8 @@ def test_generate(configuration: Configuration, result: Result, package_python_s
"""
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
result.add_failed(package_python_schedule)
report = Console("x86_64", configuration, "console")
_, repository_id = configuration.check_loaded()
report = Console(repository_id, configuration, "console")
report.generate([], result)
print_mock.assert_has_calls([MockCall(verbose=True), MockCall(verbose=True)])

View File

@ -8,17 +8,16 @@ from ahriman.models.package import Package
from ahriman.models.result import Result
def test_send(configuration: Configuration, mocker: MockerFixture) -> None:
def test_send(email: Email, mocker: MockerFixture) -> None:
"""
must send an email with attachment
"""
smtp_mock = mocker.patch("smtplib.SMTP")
report = Email("x86_64", configuration, "email")
report._send("a text", {"attachment.html": "an attachment"})
email._send("a text", {"attachment.html": "an attachment"})
smtp_mock.return_value.starttls.assert_not_called()
smtp_mock.return_value.login.assert_not_called()
smtp_mock.return_value.sendmail.assert_called_once_with(report.sender, report.receivers, pytest.helpers.anyvar(int))
smtp_mock.return_value.sendmail.assert_called_once_with(email.sender, email.receivers, pytest.helpers.anyvar(int))
smtp_mock.return_value.quit.assert_called_once_with()
@ -29,10 +28,11 @@ def test_send_auth(configuration: Configuration, mocker: MockerFixture) -> None:
configuration.set_option("email", "user", "username")
configuration.set_option("email", "password", "password")
smtp_mock = mocker.patch("smtplib.SMTP")
_, repository_id = configuration.check_loaded()
report = Email("x86_64", configuration, "email")
report._send("a text", {"attachment.html": "an attachment"})
smtp_mock.return_value.login.assert_called_once_with(report.user, report.password)
email = Email(repository_id, configuration, "email")
email._send("a text", {"attachment.html": "an attachment"})
smtp_mock.return_value.login.assert_called_once_with(email.user, email.password)
def test_send_auth_no_password(configuration: Configuration, mocker: MockerFixture) -> None:
@ -41,9 +41,10 @@ def test_send_auth_no_password(configuration: Configuration, mocker: MockerFixtu
"""
configuration.set_option("email", "user", "username")
smtp_mock = mocker.patch("smtplib.SMTP")
_, repository_id = configuration.check_loaded()
report = Email("x86_64", configuration, "email")
report._send("a text", {"attachment.html": "an attachment"})
email = Email(repository_id, configuration, "email")
email._send("a text", {"attachment.html": "an attachment"})
smtp_mock.return_value.login.assert_not_called()
@ -53,9 +54,10 @@ def test_send_auth_no_user(configuration: Configuration, mocker: MockerFixture)
"""
configuration.set_option("email", "password", "password")
smtp_mock = mocker.patch("smtplib.SMTP")
_, repository_id = configuration.check_loaded()
report = Email("x86_64", configuration, "email")
report._send("a text", {"attachment.html": "an attachment"})
email = Email(repository_id, configuration, "email")
email._send("a text", {"attachment.html": "an attachment"})
smtp_mock.return_value.login.assert_not_called()
@ -65,12 +67,13 @@ def test_send_ssl_tls(configuration: Configuration, mocker: MockerFixture) -> No
"""
configuration.set_option("email", "ssl", "ssl")
smtp_mock = mocker.patch("smtplib.SMTP_SSL")
_, repository_id = configuration.check_loaded()
report = Email("x86_64", configuration, "email")
report._send("a text", {"attachment.html": "an attachment"})
email = Email(repository_id, configuration, "email")
email._send("a text", {"attachment.html": "an attachment"})
smtp_mock.return_value.starttls.assert_not_called()
smtp_mock.return_value.login.assert_not_called()
smtp_mock.return_value.sendmail.assert_called_once_with(report.sender, report.receivers, pytest.helpers.anyvar(int))
smtp_mock.return_value.sendmail.assert_called_once_with(email.sender, email.receivers, pytest.helpers.anyvar(int))
smtp_mock.return_value.quit.assert_called_once_with()
@ -80,48 +83,40 @@ def test_send_starttls(configuration: Configuration, mocker: MockerFixture) -> N
"""
configuration.set_option("email", "ssl", "starttls")
smtp_mock = mocker.patch("smtplib.SMTP")
_, repository_id = configuration.check_loaded()
report = Email("x86_64", configuration, "email")
report._send("a text", {"attachment.html": "an attachment"})
email = Email(repository_id, configuration, "email")
email._send("a text", {"attachment.html": "an attachment"})
smtp_mock.return_value.starttls.assert_called_once_with()
def test_generate(configuration: Configuration, package_ahriman: Package, mocker: MockerFixture) -> None:
def test_generate(email: Email, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must generate report
"""
send_mock = mocker.patch("ahriman.core.report.email.Email._send")
report = Email("x86_64", configuration, "email")
report.generate([package_ahriman], Result())
email.generate([package_ahriman], Result())
send_mock.assert_called_once_with(pytest.helpers.anyvar(int), {})
def test_generate_with_built(configuration: Configuration, package_ahriman: Package, result: Result,
mocker: MockerFixture) -> None:
def test_generate_with_built(email: Email, package_ahriman: Package, result: Result, mocker: MockerFixture) -> None:
"""
must generate report with built packages
"""
send_mock = mocker.patch("ahriman.core.report.email.Email._send")
report = Email("x86_64", configuration, "email")
report.generate([package_ahriman], result)
email.generate([package_ahriman], result)
send_mock.assert_called_once_with(pytest.helpers.anyvar(int), {})
def test_generate_with_built_and_full_path(
configuration: Configuration,
package_ahriman: Package,
result: Result,
mocker: MockerFixture) -> None:
def test_generate_with_built_and_full_path(email: Email, package_ahriman: Package, result: Result,
mocker: MockerFixture) -> None:
"""
must generate report with built packages and full packages lists
"""
send_mock = mocker.patch("ahriman.core.report.email.Email._send")
report = Email("x86_64", configuration, "email")
report.full_template_path = report.template_path
report.generate([package_ahriman], result)
email.full_template_path = email.template_path
email.generate([package_ahriman], result)
send_mock.assert_called_once_with(pytest.helpers.anyvar(int), pytest.helpers.anyvar(int))
@ -131,9 +126,10 @@ def test_generate_no_empty(configuration: Configuration, package_ahriman: Packag
"""
configuration.set_option("email", "no_empty_report", "yes")
send_mock = mocker.patch("ahriman.core.report.email.Email._send")
_, repository_id = configuration.check_loaded()
report = Email("x86_64", configuration, "email")
report.generate([package_ahriman], Result())
email = Email(repository_id, configuration, "email")
email.generate([package_ahriman], Result())
send_mock.assert_not_called()
@ -144,7 +140,8 @@ def test_generate_no_empty_with_built(configuration: Configuration, package_ahri
"""
configuration.set_option("email", "no_empty_report", "yes")
send_mock = mocker.patch("ahriman.core.report.email.Email._send")
_, repository_id = configuration.check_loaded()
report = Email("x86_64", configuration, "email")
report.generate([package_ahriman], result)
email = Email(repository_id, configuration, "email")
email.generate([package_ahriman], result)
send_mock.assert_called_once_with(pytest.helpers.anyvar(int), {})

View File

@ -13,7 +13,8 @@ def test_generate(configuration: Configuration, package_ahriman: Package, mocker
must generate report
"""
write_mock = mocker.patch("pathlib.Path.write_text")
_, repository_id = configuration.check_loaded()
report = HTML("x86_64", configuration, "html")
report = HTML(repository_id, configuration, "html")
report.generate([package_ahriman], Result())
write_mock.assert_called_once_with(pytest.helpers.anyvar(int), encoding="utf8")

View File

@ -9,5 +9,6 @@ def test_generate(configuration: Configuration, package_ahriman: Package) -> Non
must generate html report
"""
path = configuration.getpath("html", "template_path")
report = JinjaTemplate("html", configuration)
_, repository_id = configuration.check_loaded()
report = JinjaTemplate(repository_id, configuration, "html")
assert report.make_html(Result(success=[package_ahriman]), path)

View File

@ -14,8 +14,10 @@ def test_report_failure(configuration: Configuration, mocker: MockerFixture) ->
must raise ReportFailed on errors
"""
mocker.patch("ahriman.core.report.html.HTML.generate", side_effect=Exception())
_, repository_id = configuration.check_loaded()
with pytest.raises(ReportError):
Report.load("x86_64", configuration, "html").run(Result(), [])
Report.load(repository_id, configuration, "html").run(Result(), [])
def test_report_dummy(configuration: Configuration, result: Result, mocker: MockerFixture) -> None:
@ -24,8 +26,9 @@ def test_report_dummy(configuration: Configuration, result: Result, mocker: Mock
"""
mocker.patch("ahriman.models.report_settings.ReportSettings.from_option", return_value=ReportSettings.Disabled)
report_mock = mocker.patch("ahriman.core.report.report.Report.generate")
_, repository_id = configuration.check_loaded()
Report.load("x86_64", configuration, "disabled").run(result, [])
Report.load(repository_id, configuration, "disabled").run(result, [])
report_mock.assert_called_once_with([], result)
@ -34,7 +37,9 @@ def test_report_console(configuration: Configuration, result: Result, mocker: Mo
must generate console report
"""
report_mock = mocker.patch("ahriman.core.report.console.Console.generate")
Report.load("x86_64", configuration, "console").run(result, [])
_, repository_id = configuration.check_loaded()
Report.load(repository_id, configuration, "console").run(result, [])
report_mock.assert_called_once_with([], result)
@ -43,7 +48,9 @@ def test_report_email(configuration: Configuration, result: Result, mocker: Mock
must generate email report
"""
report_mock = mocker.patch("ahriman.core.report.email.Email.generate")
Report.load("x86_64", configuration, "email").run(result, [])
_, repository_id = configuration.check_loaded()
Report.load(repository_id, configuration, "email").run(result, [])
report_mock.assert_called_once_with([], result)
@ -52,7 +59,9 @@ def test_report_html(configuration: Configuration, result: Result, mocker: Mocke
must generate html report
"""
report_mock = mocker.patch("ahriman.core.report.html.HTML.generate")
Report.load("x86_64", configuration, "html").run(result, [])
_, repository_id = configuration.check_loaded()
Report.load(repository_id, configuration, "html").run(result, [])
report_mock.assert_called_once_with([], result)
@ -63,8 +72,9 @@ def test_report_remote_call(configuration: Configuration, result: Result, mocker
configuration.set_option("web", "host", "localhost")
configuration.set_option("web", "port", "8080")
report_mock = mocker.patch("ahriman.core.report.remote_call.RemoteCall.generate")
_, repository_id = configuration.check_loaded()
Report.load("x86_64", configuration, "remote-call").run(result, [])
Report.load(repository_id, configuration, "remote-call").run(result, [])
report_mock.assert_called_once_with([], result)
@ -73,5 +83,7 @@ def test_report_telegram(configuration: Configuration, result: Result, mocker: M
must generate telegram report
"""
report_mock = mocker.patch("ahriman.core.report.telegram.Telegram.generate")
Report.load("x86_64", configuration, "telegram").run(result, [])
_, repository_id = configuration.check_loaded()
Report.load(repository_id, configuration, "telegram").run(result, [])
report_mock.assert_called_once_with([], result)

View File

@ -22,7 +22,8 @@ def test_on_result(configuration: Configuration, mocker: MockerFixture) -> None:
"""
configuration.set_option("report", "target", "email")
run_mock = mocker.patch("ahriman.core.report.report.Report.run")
_, repository_id = configuration.check_loaded()
trigger = ReportTrigger("x86_64", configuration)
trigger = ReportTrigger(repository_id, configuration)
trigger.on_result(Result(), [])
run_mock.assert_called_once_with(Result(), [])

View File

@ -10,67 +10,58 @@ from ahriman.models.package import Package
from ahriman.models.result import Result
def test_send(configuration: Configuration, mocker: MockerFixture) -> None:
def test_send(telegram: Telegram, mocker: MockerFixture) -> None:
"""
must send a message
"""
request_mock = mocker.patch("ahriman.core.report.telegram.Telegram.make_request")
report = Telegram("x86_64", configuration, "telegram")
report._send("a text")
telegram._send("a text")
request_mock.assert_called_once_with(
"POST",
pytest.helpers.anyvar(str, strict=True),
data={"chat_id": pytest.helpers.anyvar(str, strict=True), "text": "a text", "parse_mode": "HTML"})
def test_send_failed(configuration: Configuration, mocker: MockerFixture) -> None:
def test_send_failed(telegram: Telegram, mocker: MockerFixture) -> None:
"""
must reraise generic exception
"""
mocker.patch("requests.Session.request", side_effect=Exception())
report = Telegram("x86_64", configuration, "telegram")
with pytest.raises(Exception):
report._send("a text")
telegram._send("a text")
def test_send_failed_http_error(configuration: Configuration, mocker: MockerFixture) -> None:
def test_send_failed_http_error(telegram: Telegram, mocker: MockerFixture) -> None:
"""
must reraise http exception
"""
mocker.patch("requests.Session.request", side_effect=requests.HTTPError())
report = Telegram("x86_64", configuration, "telegram")
with pytest.raises(requests.HTTPError):
report._send("a text")
telegram._send("a text")
def test_generate(configuration: Configuration, package_ahriman: Package, result: Result,
def test_generate(telegram: Telegram, package_ahriman: Package, result: Result,
mocker: MockerFixture) -> None:
"""
must generate report
"""
send_mock = mocker.patch("ahriman.core.report.telegram.Telegram._send")
report = Telegram("x86_64", configuration, "telegram")
report.generate([package_ahriman], result)
telegram.generate([package_ahriman], result)
send_mock.assert_called_once_with(pytest.helpers.anyvar(int))
def test_generate_big_text_without_spaces(configuration: Configuration, package_ahriman: Package, result: Result,
def test_generate_big_text_without_spaces(telegram: Telegram, package_ahriman: Package, result: Result,
mocker: MockerFixture) -> None:
"""
must raise ValueError in case if there are no new lines in text
"""
mocker.patch("ahriman.core.report.jinja_template.JinjaTemplate.make_html", return_value="ab" * 4096)
report = Telegram("x86_64", configuration, "telegram")
with pytest.raises(ValueError):
report.generate([package_ahriman], result)
telegram.generate([package_ahriman], result)
def test_generate_big_text(configuration: Configuration, package_ahriman: Package, result: Result,
def test_generate_big_text(telegram: Telegram, package_ahriman: Package, result: Result,
mocker: MockerFixture) -> None:
"""
must generate report with big text
@ -78,14 +69,13 @@ def test_generate_big_text(configuration: Configuration, package_ahriman: Packag
mocker.patch("ahriman.core.report.jinja_template.JinjaTemplate.make_html", return_value="a\n" * 4096)
send_mock = mocker.patch("ahriman.core.report.telegram.Telegram._send")
report = Telegram("x86_64", configuration, "telegram")
report.generate([package_ahriman], result)
telegram.generate([package_ahriman], result)
send_mock.assert_has_calls([
MockCall(pytest.helpers.anyvar(str, strict=True)), MockCall(pytest.helpers.anyvar(str, strict=True))
])
def test_generate_very_big_text(configuration: Configuration, package_ahriman: Package, result: Result,
def test_generate_very_big_text(telegram: Telegram, package_ahriman: Package, result: Result,
mocker: MockerFixture) -> None:
"""
must generate report with very big text
@ -93,8 +83,7 @@ def test_generate_very_big_text(configuration: Configuration, package_ahriman: P
mocker.patch("ahriman.core.report.jinja_template.JinjaTemplate.make_html", return_value="ab\n" * 4096)
send_mock = mocker.patch("ahriman.core.report.telegram.Telegram._send")
report = Telegram("x86_64", configuration, "telegram")
report.generate([package_ahriman], result)
telegram.generate([package_ahriman], result)
send_mock.assert_has_calls([
MockCall(pytest.helpers.anyvar(str, strict=True)),
MockCall(pytest.helpers.anyvar(str, strict=True)),
@ -102,12 +91,10 @@ def test_generate_very_big_text(configuration: Configuration, package_ahriman: P
])
def test_generate_no_empty(configuration: Configuration, package_ahriman: Package, mocker: MockerFixture) -> None:
def test_generate_no_empty(telegram: Telegram, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must generate report
"""
send_mock = mocker.patch("ahriman.core.report.telegram.Telegram._send")
report = Telegram("x86_64", configuration, "telegram")
report.generate([package_ahriman], Result())
telegram.generate([package_ahriman], Result())
send_mock.assert_not_called()

View File

@ -22,7 +22,8 @@ def cleaner(configuration: Configuration, database: SQLite) -> Cleaner:
Returns:
Cleaner: cleaner test instance
"""
return Cleaner("x86_64", configuration, database, report=False,
_, repository_id = configuration.check_loaded()
return Cleaner(repository_id, configuration, database, report=False,
refresh_pacman_database=PacmanSynchronization.Disabled)
@ -43,7 +44,8 @@ def executor(configuration: Configuration, database: SQLite, mocker: MockerFixtu
mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_chroot")
mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_packages")
mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_queue")
return Executor("x86_64", configuration, database, report=False,
_, repository_id = configuration.check_loaded()
return Executor(repository_id, configuration, database, report=False,
refresh_pacman_database=PacmanSynchronization.Disabled)
@ -64,5 +66,6 @@ def update_handler(configuration: Configuration, database: SQLite, mocker: Mocke
mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_chroot")
mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_packages")
mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_queue")
return UpdateHandler("x86_64", configuration, database, report=False,
_, repository_id = configuration.check_loaded()
return UpdateHandler(repository_id, configuration, database, report=False,
refresh_pacman_database=PacmanSynchronization.Disabled)

View File

@ -20,7 +20,9 @@ def test_load(configuration: Configuration, database: SQLite, mocker: MockerFixt
must correctly load instance
"""
context_mock = mocker.patch("ahriman.core.repository.Repository._set_context")
Repository.load("x86_64", configuration, database, report=False)
_, repository_id = configuration.check_loaded()
Repository.load(repository_id, configuration, database, report=False)
context_mock.assert_called_once_with()
@ -29,8 +31,9 @@ def test_set_context(configuration: Configuration, database: SQLite, mocker: Moc
must set context variables
"""
set_mock = mocker.patch("ahriman.core._Context.set")
_, repository_id = configuration.check_loaded()
instance = Repository.load("x86_64", configuration, database, report=False)
instance = Repository.load(repository_id, configuration, database, report=False)
set_mock.assert_has_calls([
MockCall(ContextKey("database", SQLite), instance.database),
MockCall(ContextKey("configuration", Configuration), instance.configuration),

View File

@ -6,6 +6,20 @@ from ahriman.models.user import User
from ahriman.models.user_access import UserAccess
def test_architecture(repository: RepositoryProperties) -> None:
"""
must provide repository architecture for backward compatibility
"""
assert repository.architecture == repository.repository_id.architecture
def test_name(repository: RepositoryProperties) -> None:
"""
must provide repository name for backward compatibility
"""
assert repository.name == repository.repository_id.name
def test_packager(repository: RepositoryProperties, mocker: MockerFixture) -> None:
"""
must extract packager

View File

@ -17,9 +17,10 @@ def test_force_no_report(configuration: Configuration, database: SQLite, mocker:
"""
configuration.set_option("web", "port", "8080")
load_mock = mocker.patch("ahriman.core.repository.Repository.load")
_, repository_id = configuration.check_loaded()
Watcher("x86_64", configuration, database)
load_mock.assert_called_once_with("x86_64", configuration, database, report=False)
Watcher(repository_id, configuration, database)
load_mock.assert_called_once_with(repository_id, configuration, database, report=False)
def test_load(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:

View File

@ -16,7 +16,8 @@ def mirrorlist_generator(configuration: Configuration) -> MirrorlistGenerator:
Returns:
MirrorlistGenerator: mirrorlist pkgbuild generator test instance
"""
return MirrorlistGenerator(configuration, "mirrorlist")
_, repository_id = configuration.check_loaded()
return MirrorlistGenerator(repository_id, configuration, "mirrorlist")
@pytest.fixture

View File

@ -20,7 +20,8 @@ def keyring_generator(database: SQLite, gpg: GPG, configuration: Configuration)
Returns:
KeyringGenerator: keyring generator test instance
"""
return KeyringGenerator(database, gpg, configuration, "keyring")
_, repository_id = configuration.check_loaded()
return KeyringGenerator(database, gpg, repository_id, configuration, "keyring")
@pytest.fixture

View File

@ -18,74 +18,87 @@ def test_init_packagers(database: SQLite, gpg: GPG, configuration: Configuration
must extract packagers keys
"""
mocker.patch("ahriman.core.database.SQLite.user_list", return_value=[user])
_, repository_id = configuration.check_loaded()
assert KeyringGenerator(database, gpg, configuration, "keyring").packagers == ["key"]
assert KeyringGenerator(database, gpg, repository_id, configuration, "keyring").packagers == ["key"]
configuration.set_option("keyring", "packagers", "key1")
assert KeyringGenerator(database, gpg, configuration, "keyring").packagers == ["key1"]
assert KeyringGenerator(database, gpg, repository_id, configuration, "keyring").packagers == ["key1"]
def test_init_revoked(database: SQLite, gpg: GPG, configuration: Configuration) -> None:
"""
must extract revoked keys
"""
assert KeyringGenerator(database, gpg, configuration, "keyring").revoked == []
_, repository_id = configuration.check_loaded()
assert KeyringGenerator(database, gpg, repository_id, configuration, "keyring").revoked == []
configuration.set_option("keyring", "revoked", "key1")
assert KeyringGenerator(database, gpg, configuration, "keyring").revoked == ["key1"]
assert KeyringGenerator(database, gpg, repository_id, configuration, "keyring").revoked == ["key1"]
def test_init_trusted(database: SQLite, gpg: GPG, configuration: Configuration) -> None:
"""
must extract trusted keys
"""
assert KeyringGenerator(database, gpg, configuration, "keyring").trusted == []
_, repository_id = configuration.check_loaded()
assert KeyringGenerator(database, gpg, repository_id, configuration, "keyring").trusted == []
gpg.default_key = "key"
assert KeyringGenerator(database, gpg, configuration, "keyring").trusted == ["key"]
assert KeyringGenerator(database, gpg, repository_id, configuration, "keyring").trusted == ["key"]
configuration.set_option("keyring", "trusted", "key1")
assert KeyringGenerator(database, gpg, configuration, "keyring").trusted == ["key1"]
assert KeyringGenerator(database, gpg, repository_id, configuration, "keyring").trusted == ["key1"]
def test_license(database: SQLite, gpg: GPG, configuration: Configuration) -> None:
"""
must generate correct licenses list
"""
assert KeyringGenerator(database, gpg, configuration, "keyring").license == ["Unlicense"]
_, repository_id = configuration.check_loaded()
assert KeyringGenerator(database, gpg, repository_id, configuration, "keyring").license == ["Unlicense"]
configuration.set_option("keyring", "license", "GPL MPL")
assert KeyringGenerator(database, gpg, configuration, "keyring").license == ["GPL", "MPL"]
assert KeyringGenerator(database, gpg, repository_id, configuration, "keyring").license == ["GPL", "MPL"]
def test_pkgdesc(database: SQLite, gpg: GPG, configuration: Configuration) -> None:
"""
must generate correct pkgdesc property
"""
assert KeyringGenerator(database, gpg, configuration, "keyring").pkgdesc == "aur-clone PGP keyring"
_, repository_id = configuration.check_loaded()
assert KeyringGenerator(database, gpg, repository_id, configuration, "keyring").pkgdesc == "aur-clone PGP keyring"
configuration.set_option("keyring", "description", "description")
assert KeyringGenerator(database, gpg, configuration, "keyring").pkgdesc == "description"
assert KeyringGenerator(database, gpg, repository_id, configuration, "keyring").pkgdesc == "description"
def test_pkgname(database: SQLite, gpg: GPG, configuration: Configuration) -> None:
"""
must generate correct pkgname property
"""
assert KeyringGenerator(database, gpg, configuration, "keyring").pkgname == "aur-clone-keyring"
_, repository_id = configuration.check_loaded()
assert KeyringGenerator(database, gpg, repository_id, configuration, "keyring").pkgname == "aur-clone-keyring"
configuration.set_option("keyring", "package", "keyring")
assert KeyringGenerator(database, gpg, configuration, "keyring").pkgname == "keyring"
assert KeyringGenerator(database, gpg, repository_id, configuration, "keyring").pkgname == "keyring"
def test_url(database: SQLite, gpg: GPG, configuration: Configuration) -> None:
"""
must generate correct url property
"""
assert KeyringGenerator(database, gpg, configuration, "keyring").url == ""
_, repository_id = configuration.check_loaded()
assert KeyringGenerator(database, gpg, repository_id, configuration, "keyring").url == ""
configuration.set_option("keyring", "homepage", "homepage")
assert KeyringGenerator(database, gpg, configuration, "keyring").url == "homepage"
assert KeyringGenerator(database, gpg, repository_id, configuration, "keyring").url == "homepage"
def test_generate_gpg(keyring_generator: KeyringGenerator, mocker: MockerFixture) -> None:

View File

@ -9,50 +9,62 @@ def test_init_path(configuration: Configuration) -> None:
"""
must set relative path to mirrorlist
"""
assert MirrorlistGenerator(configuration, "mirrorlist").path == Path("etc") / "pacman.d" / "aur-clone-mirrorlist"
_, repository_id = configuration.check_loaded()
assert MirrorlistGenerator(repository_id, configuration, "mirrorlist").path == \
Path("etc") / "pacman.d" / "aur-clone-mirrorlist"
configuration.set_option("mirrorlist", "path", "/etc")
assert MirrorlistGenerator(configuration, "mirrorlist").path == Path("etc")
assert MirrorlistGenerator(repository_id, configuration, "mirrorlist").path == Path("etc")
def test_license(configuration: Configuration) -> None:
"""
must generate correct licenses list
"""
assert MirrorlistGenerator(configuration, "mirrorlist").license == ["Unlicense"]
_, repository_id = configuration.check_loaded()
assert MirrorlistGenerator(repository_id, configuration, "mirrorlist").license == ["Unlicense"]
configuration.set_option("mirrorlist", "license", "GPL MPL")
assert MirrorlistGenerator(configuration, "mirrorlist").license == ["GPL", "MPL"]
assert MirrorlistGenerator(repository_id, configuration, "mirrorlist").license == ["GPL", "MPL"]
def test_pkgdesc(configuration: Configuration) -> None:
"""
must generate correct pkgdesc property
"""
assert MirrorlistGenerator(configuration, "mirrorlist").pkgdesc == "aur-clone mirror list for use by pacman"
_, repository_id = configuration.check_loaded()
assert MirrorlistGenerator(repository_id, configuration, "mirrorlist").pkgdesc == \
"aur-clone mirror list for use by pacman"
configuration.set_option("mirrorlist", "description", "description")
assert MirrorlistGenerator(configuration, "mirrorlist").pkgdesc == "description"
assert MirrorlistGenerator(repository_id, configuration, "mirrorlist").pkgdesc == "description"
def test_pkgname(configuration: Configuration) -> None:
"""
must generate correct pkgname property
"""
assert MirrorlistGenerator(configuration, "mirrorlist").pkgname == "aur-clone-mirrorlist"
_, repository_id = configuration.check_loaded()
assert MirrorlistGenerator(repository_id, configuration, "mirrorlist").pkgname == "aur-clone-mirrorlist"
configuration.set_option("mirrorlist", "package", "mirrorlist")
assert MirrorlistGenerator(configuration, "mirrorlist").pkgname == "mirrorlist"
assert MirrorlistGenerator(repository_id, configuration, "mirrorlist").pkgname == "mirrorlist"
def test_url(configuration: Configuration) -> None:
"""
must generate correct url property
"""
assert MirrorlistGenerator(configuration, "mirrorlist").url == ""
_, repository_id = configuration.check_loaded()
assert MirrorlistGenerator(repository_id, configuration, "mirrorlist").url == ""
configuration.set_option("mirrorlist", "homepage", "homepage")
assert MirrorlistGenerator(configuration, "mirrorlist").url == "homepage"
assert MirrorlistGenerator(repository_id, configuration, "mirrorlist").url == "homepage"
def test_generate_mirrorlist(mirrorlist_generator: MirrorlistGenerator, mocker: MockerFixture) -> None:

View File

@ -25,8 +25,9 @@ def test_on_start(configuration: Configuration, mocker: MockerFixture) -> None:
"""
context_mock = mocker.patch("ahriman.core._Context.get")
run_mock = mocker.patch("ahriman.core.support.package_creator.PackageCreator.run")
_, repository_id = configuration.check_loaded()
trigger = KeyringTrigger("x86_64", configuration)
trigger = KeyringTrigger(repository_id, configuration)
trigger.on_start()
context_mock.assert_has_calls([MockCall(ContextKey("sign", GPG)), MockCall(ContextKey("database", SQLite))])
run_mock.assert_called_once_with()

View File

@ -20,7 +20,8 @@ def test_on_start(configuration: Configuration, mocker: MockerFixture) -> None:
must run report for specified targets
"""
run_mock = mocker.patch("ahriman.core.support.package_creator.PackageCreator.run")
_, repository_id = configuration.check_loaded()
trigger = MirrorlistTrigger("x86_64", configuration)
trigger = MirrorlistTrigger(repository_id, configuration)
trigger.on_start()
run_mock.assert_called_once_with()

View File

@ -7,6 +7,8 @@ from ahriman.core.support.package_creator import PackageCreator
from ahriman.models.context_key import ContextKey
from ahriman.models.package import Package
from ahriman.models.package_description import PackageDescription
from ahriman.models.package_source import PackageSource
from ahriman.models.remote_source import RemoteSource
def test_run(package_creator: PackageCreator, database: SQLite, mocker: MockerFixture) -> None:
@ -16,7 +18,7 @@ def test_run(package_creator: PackageCreator, database: SQLite, mocker: MockerFi
package = Package(
base=package_creator.generator.pkgname,
version=package_creator.generator.pkgver,
remote=None,
remote=RemoteSource(source=PackageSource.Local),
packages={package_creator.generator.pkgname: PackageDescription()},
)
local_path = package_creator.configuration.repository_paths.cache_for(package_creator.generator.pkgname)

View File

@ -20,9 +20,9 @@ def test_process(spawner: Spawn) -> None:
callback = MagicMock()
callback.return_value = True
spawner.process(callback, args, spawner.architecture, "id", spawner.queue)
spawner.process(callback, args, spawner.repository_id, "id", spawner.queue)
callback.assert_called_once_with(args, spawner.architecture)
callback.assert_called_once_with(args, spawner.repository_id)
(uuid, status, time) = spawner.queue.get()
assert uuid == "id"
assert status
@ -37,7 +37,7 @@ def test_process_error(spawner: Spawn) -> None:
callback = MagicMock()
callback.return_value = False
spawner.process(callback, MagicMock(), spawner.architecture, "id", spawner.queue)
spawner.process(callback, MagicMock(), spawner.repository_id, "id", spawner.queue)
(uuid, status, time) = spawner.queue.get()
assert uuid == "id"

View File

@ -15,7 +15,8 @@ def trigger(configuration: Configuration) -> Trigger:
Returns:
Trigger: trigger test instance
"""
return Trigger("x86_64", configuration)
_, repository_id = configuration.check_loaded()
return Trigger(repository_id, configuration)
@pytest.fixture
@ -28,4 +29,5 @@ def trigger_loader(configuration: Configuration) -> TriggerLoader:
Returns:
TriggerLoader: trigger loader test instance
"""
return TriggerLoader.load("x86_64", configuration)
_, repository_id = configuration.check_loaded()
return TriggerLoader.load(repository_id, configuration)

View File

@ -6,15 +6,23 @@ from ahriman.core.triggers import Trigger
from ahriman.models.result import Result
def test_architecture(trigger: Trigger) -> None:
"""
must return repository architecture for backward compatibility
"""
assert trigger.architecture == trigger.repository_id.architecture
def test_configuration_schema(configuration: Configuration) -> None:
"""
must return used configuration schema
"""
section = "console"
configuration.set_option("report", "target", section)
_, repository_id = configuration.check_loaded()
expected = {section: ReportTrigger.CONFIGURATION_SCHEMA[section]}
assert ReportTrigger.configuration_schema("x86_64", configuration) == expected
assert ReportTrigger.configuration_schema(repository_id, configuration) == expected
def test_configuration_schema_no_section(configuration: Configuration) -> None:
@ -23,7 +31,9 @@ def test_configuration_schema_no_section(configuration: Configuration) -> None:
"""
section = "abracadabra"
configuration.set_option("report", "target", section)
assert ReportTrigger.configuration_schema("x86_64", configuration) == {}
_, repository_id = configuration.check_loaded()
assert ReportTrigger.configuration_schema(repository_id, configuration) == {}
def test_configuration_schema_no_schema(configuration: Configuration) -> None:
@ -33,15 +43,17 @@ def test_configuration_schema_no_schema(configuration: Configuration) -> None:
section = "abracadabra"
configuration.set_option("report", "target", section)
configuration.set_option(section, "key", "value")
_, repository_id = configuration.check_loaded()
assert ReportTrigger.configuration_schema("x86_64", configuration) == {}
assert ReportTrigger.configuration_schema(repository_id, configuration) == {}
def test_configuration_schema_empty() -> None:
def test_configuration_schema_empty(configuration: Configuration) -> None:
"""
must return default schema if no configuration set
"""
assert ReportTrigger.configuration_schema("x86_64", None) == ReportTrigger.CONFIGURATION_SCHEMA
_, repository_id = configuration.check_loaded()
assert ReportTrigger.configuration_schema(repository_id, None) == ReportTrigger.CONFIGURATION_SCHEMA
def test_configuration_schema_variables(configuration: Configuration) -> None:

View File

@ -48,8 +48,10 @@ def test_load_trigger_package_error_on_creation(trigger_loader: TriggerLoader, c
must raise InvalidException on trigger initialization if any exception is thrown
"""
mocker.patch("ahriman.core.triggers.trigger.Trigger.__init__", side_effect=Exception())
_, repository_id = configuration.check_loaded()
with pytest.raises(ExtensionError):
trigger_loader.load_trigger("ahriman.core.report.ReportTrigger", "x86_64", configuration)
trigger_loader.load_trigger("ahriman.core.report.ReportTrigger", repository_id, configuration)
def test_load_trigger_class_package(trigger_loader: TriggerLoader) -> None:
@ -155,8 +157,9 @@ def test_on_stop_with_on_start(configuration: Configuration, mocker: MockerFixtu
mocker.patch("ahriman.core.upload.UploadTrigger.on_start")
mocker.patch("ahriman.core.report.ReportTrigger.on_start")
on_stop_mock = mocker.patch("ahriman.core.triggers.trigger_loader.TriggerLoader.on_stop")
_, repository_id = configuration.check_loaded()
trigger_loader = TriggerLoader.load("x86_64", configuration)
trigger_loader = TriggerLoader.load(repository_id, configuration)
trigger_loader.on_start()
del trigger_loader
on_stop_mock.assert_called_once_with()
@ -167,8 +170,9 @@ def test_on_stop_without_on_start(configuration: Configuration, mocker: MockerFi
must call not on_stop on exit if on_start wasn't called
"""
on_stop_mock = mocker.patch("ahriman.core.triggers.trigger_loader.TriggerLoader.on_stop")
_, repository_id = configuration.check_loaded()
trigger_loader = TriggerLoader.load("x86_64", configuration)
trigger_loader = TriggerLoader.load(repository_id, configuration)
del trigger_loader
on_stop_mock.assert_not_called()

View File

@ -4,33 +4,34 @@ from typing import Any
from unittest.mock import MagicMock
from ahriman.core.configuration import Configuration
from ahriman.core.upload.github import Github
from ahriman.core.upload.github import GitHub
from ahriman.core.upload.remote_service import RemoteService
from ahriman.core.upload.rsync import Rsync
from ahriman.core.upload.s3 import S3
@pytest.fixture
def github(configuration: Configuration) -> Github:
def github(configuration: Configuration) -> GitHub:
"""
fixture for github synchronization
fixture for GitHub synchronization
Args:
configuration(Configuration): configuration fixture
Returns:
Github: github test instance
GitHub: GitHub test instance
"""
return Github("x86_64", configuration, "github:x86_64")
_, repository_id = configuration.check_loaded()
return GitHub(repository_id, configuration, "github:x86_64")
@pytest.fixture
def github_release() -> dict[str, Any]:
"""
fixture for the github release object
fixture for the GitHub release object
Returns:
dict[str, Any]: github test release object
dict[str, Any]: GitHub test release object
"""
return {
"url": "release_url",
@ -59,7 +60,8 @@ def remote_service(configuration: Configuration) -> RemoteService:
"""
configuration.set_option("web", "host", "localhost")
configuration.set_option("web", "port", "8080")
return RemoteService("x86_64", configuration, "remote-service")
_, repository_id = configuration.check_loaded()
return RemoteService(repository_id, configuration, "remote-service")
@pytest.fixture
@ -73,7 +75,8 @@ def rsync(configuration: Configuration) -> Rsync:
Returns:
Rsync: rsync test instance
"""
return Rsync("x86_64", configuration, "rsync")
_, repository_id = configuration.check_loaded()
return Rsync(repository_id, configuration, "rsync")
@pytest.fixture
@ -87,23 +90,25 @@ def s3(configuration: Configuration) -> S3:
Returns:
S3: S3 test instance
"""
return S3("x86_64", configuration, "customs3")
_, repository_id = configuration.check_loaded()
return S3(repository_id, configuration, "customs3")
@pytest.fixture
def s3_remote_objects() -> list[MagicMock]:
def s3_remote_objects(configuration: Configuration) -> list[MagicMock]:
"""
fixture for boto3 like S3 objects
Returns:
list[MagicMock]: boto3 like S3 objects test instance
"""
_, repository_id = configuration.check_loaded()
delete_mock = MagicMock()
result = []
for item in ["a", "b", "c"]:
s3_object = MagicMock()
s3_object.key = f"x86_64/{item}"
s3_object.key = f"{repository_id.name}/{repository_id.architecture}/{item}"
s3_object.e_tag = f"\"{item}\""
s3_object.delete = delete_mock

View File

@ -6,34 +6,50 @@ from pytest_mock import MockerFixture
from typing import Any
from unittest.mock import call as MockCall
from ahriman.core.upload.github import Github
from ahriman.core.configuration import Configuration
from ahriman.core.upload.github import GitHub
def test_asset_remove(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None:
def test_github_release_tag(configuration: Configuration) -> None:
"""
must correctly define GitHub release tag
"""
_, repository_id = configuration.check_loaded()
instance = GitHub(repository_id, configuration, "github:x86_64")
assert instance.github_release_tag == instance.github_release_tag_name == repository_id.architecture
configuration.set_option("github:x86_64", "use_full_release_name", "yes")
instance = GitHub(repository_id, configuration, "github:x86_64")
assert instance.github_release_tag == f"{repository_id.name}-{repository_id.architecture}"
assert instance.github_release_tag_name == f"{repository_id.name} {repository_id.architecture}"
def test_asset_remove(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
"""
must remove asset from the release
"""
request_mock = mocker.patch("ahriman.core.upload.github.Github.make_request")
request_mock = mocker.patch("ahriman.core.upload.github.GitHub.make_request")
github.asset_remove(github_release, "asset_name")
request_mock.assert_called_once_with("DELETE", "asset_url")
def test_asset_remove_unknown(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None:
def test_asset_remove_unknown(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
"""
must not fail if no asset found
"""
request_mock = mocker.patch("ahriman.core.upload.github.Github.make_request")
request_mock = mocker.patch("ahriman.core.upload.github.GitHub.make_request")
github.asset_remove(github_release, "unknown_asset_name")
request_mock.assert_not_called()
def test_asset_upload(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None:
def test_asset_upload(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
"""
must upload asset to the repository
"""
mocker.patch("pathlib.Path.open")
request_mock = mocker.patch("ahriman.core.upload.github.Github.make_request")
remove_mock = mocker.patch("ahriman.core.upload.github.Github.asset_remove")
request_mock = mocker.patch("ahriman.core.upload.github.GitHub.make_request")
remove_mock = mocker.patch("ahriman.core.upload.github.GitHub.asset_remove")
github.asset_upload(github_release, Path("/root/new.tar.xz"))
request_mock.assert_called_once_with("POST", "upload_url", params=[("name", "new.tar.xz")],
@ -42,13 +58,13 @@ def test_asset_upload(github: Github, github_release: dict[str, Any], mocker: Mo
remove_mock.assert_not_called()
def test_asset_upload_with_removal(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None:
def test_asset_upload_with_removal(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
"""
must remove existing file before upload
"""
mocker.patch("pathlib.Path.open")
mocker.patch("ahriman.core.upload.github.Github.make_request")
remove_mock = mocker.patch("ahriman.core.upload.github.Github.asset_remove")
mocker.patch("ahriman.core.upload.github.GitHub.make_request")
remove_mock = mocker.patch("ahriman.core.upload.github.GitHub.asset_remove")
github.asset_upload(github_release, Path("asset_name"))
github.asset_upload(github_release, Path("/root/asset_name"))
@ -58,14 +74,14 @@ def test_asset_upload_with_removal(github: Github, github_release: dict[str, Any
])
def test_asset_upload_empty_mimetype(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None:
def test_asset_upload_empty_mimetype(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
"""
must upload asset to the repository with empty mime type if the library cannot guess it
"""
mocker.patch("pathlib.Path.open")
mocker.patch("ahriman.core.upload.github.Github.asset_remove")
mocker.patch("ahriman.core.upload.github.GitHub.asset_remove")
mocker.patch("mimetypes.guess_type", return_value=(None, None))
request_mock = mocker.patch("ahriman.core.upload.github.Github.make_request")
request_mock = mocker.patch("ahriman.core.upload.github.GitHub.make_request")
github.asset_upload(github_release, Path("/root/new.tar.xz"))
request_mock.assert_called_once_with("POST", "upload_url", params=[("name", "new.tar.xz")],
@ -73,7 +89,7 @@ def test_asset_upload_empty_mimetype(github: Github, github_release: dict[str, A
headers={"Content-Type": "application/octet-stream"})
def test_get_local_files(github: Github, resource_path_root: Path, mocker: MockerFixture) -> None:
def test_get_local_files(github: GitHub, resource_path_root: Path, mocker: MockerFixture) -> None:
"""
must get all local files recursively
"""
@ -82,29 +98,29 @@ def test_get_local_files(github: Github, resource_path_root: Path, mocker: Mocke
walk_mock.assert_called()
def test_files_remove(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None:
def test_files_remove(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
"""
must remove files from the remote
"""
remove_mock = mocker.patch("ahriman.core.upload.github.Github.asset_remove")
remove_mock = mocker.patch("ahriman.core.upload.github.GitHub.asset_remove")
github.files_remove(github_release, {Path("a"): "a"}, {"a": "a", "b": "b"})
remove_mock.assert_called_once_with(github_release, "b")
def test_files_remove_empty(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None:
def test_files_remove_empty(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
"""
must remove nothing if nothing changed
"""
remove_mock = mocker.patch("ahriman.core.upload.github.Github.asset_remove")
remove_mock = mocker.patch("ahriman.core.upload.github.GitHub.asset_remove")
github.files_remove(github_release, {Path("a"): "a"}, {"a": "a"})
remove_mock.assert_not_called()
def test_files_upload(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None:
def test_files_upload(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
"""
must upload files to the remote
"""
upload_mock = mocker.patch("ahriman.core.upload.github.Github.asset_upload")
upload_mock = mocker.patch("ahriman.core.upload.github.GitHub.asset_upload")
github.files_upload(github_release, {Path("a"): "a", Path("b"): "c", Path("c"): "c"}, {"a": "a", "b": "b"})
upload_mock.assert_has_calls([
MockCall(github_release, Path("b")),
@ -112,83 +128,84 @@ def test_files_upload(github: Github, github_release: dict[str, Any], mocker: Mo
])
def test_files_upload_empty(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None:
def test_files_upload_empty(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
"""
must upload nothing if nothing changed
"""
upload_mock = mocker.patch("ahriman.core.upload.github.Github.asset_upload")
upload_mock = mocker.patch("ahriman.core.upload.github.GitHub.asset_upload")
github.files_upload(github_release, {Path("a"): "a"}, {"a": "a"})
upload_mock.assert_not_called()
def test_release_create(github: Github, mocker: MockerFixture) -> None:
def test_release_create(github: GitHub, mocker: MockerFixture) -> None:
"""
must create release
"""
request_mock = mocker.patch("ahriman.core.upload.github.Github.make_request")
request_mock = mocker.patch("ahriman.core.upload.github.GitHub.make_request")
github.release_create()
request_mock.assert_called_once_with("POST", pytest.helpers.anyvar(str, True),
json={"tag_name": github.architecture, "name": github.architecture})
request_mock.assert_called_once_with(
"POST", pytest.helpers.anyvar(str, True),
json={"tag_name": github.github_release_tag, "name": github.github_release_tag_name})
def test_release_get(github: Github, mocker: MockerFixture) -> None:
def test_release_get(github: GitHub, mocker: MockerFixture) -> None:
"""
must get release
"""
request_mock = mocker.patch("ahriman.core.upload.github.Github.make_request")
request_mock = mocker.patch("ahriman.core.upload.github.GitHub.make_request")
github.release_get()
request_mock.assert_called_once_with("GET", pytest.helpers.anyvar(str, True))
def test_release_get_empty(github: Github, mocker: MockerFixture) -> None:
def test_release_get_empty(github: GitHub, mocker: MockerFixture) -> None:
"""
must return nothing in case of 404 status code
"""
response = requests.Response()
response.status_code = 404
mocker.patch("ahriman.core.upload.github.Github.make_request",
mocker.patch("ahriman.core.upload.github.GitHub.make_request",
side_effect=requests.HTTPError(response=response))
assert github.release_get() is None
def test_release_get_exception(github: Github, mocker: MockerFixture) -> None:
def test_release_get_exception(github: GitHub, mocker: MockerFixture) -> None:
"""
must re-raise non HTTPError exception
"""
mocker.patch("ahriman.core.upload.github.Github.make_request", side_effect=Exception())
mocker.patch("ahriman.core.upload.github.GitHub.make_request", side_effect=Exception())
with pytest.raises(Exception):
github.release_get()
def test_release_get_exception_http_error(github: Github, mocker: MockerFixture) -> None:
def test_release_get_exception_http_error(github: GitHub, mocker: MockerFixture) -> None:
"""
must re-raise HTTPError exception with code differs from 404
"""
exception = requests.HTTPError(response=requests.Response())
mocker.patch("ahriman.core.upload.github.Github.make_request", side_effect=exception)
mocker.patch("ahriman.core.upload.github.GitHub.make_request", side_effect=exception)
with pytest.raises(requests.HTTPError):
github.release_get()
def test_release_update(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None:
def test_release_update(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
"""
must update release
"""
request_mock = mocker.patch("ahriman.core.upload.github.Github.make_request")
request_mock = mocker.patch("ahriman.core.upload.github.GitHub.make_request")
github.release_update(github_release, "body")
request_mock.assert_called_once_with("POST", "release_url", json={"body": "body"})
def test_release_sync(github: Github, mocker: MockerFixture) -> None:
def test_release_sync(github: GitHub, mocker: MockerFixture) -> None:
"""
must run sync command
"""
release_get_mock = mocker.patch("ahriman.core.upload.github.Github.release_get", return_value={})
get_hashes_mock = mocker.patch("ahriman.core.upload.github.Github.get_hashes", return_value={})
get_local_files_mock = mocker.patch("ahriman.core.upload.github.Github.get_local_files", return_value={})
files_upload_mock = mocker.patch("ahriman.core.upload.github.Github.files_upload")
files_remove_mock = mocker.patch("ahriman.core.upload.github.Github.files_remove")
release_update_mock = mocker.patch("ahriman.core.upload.github.Github.release_update")
release_get_mock = mocker.patch("ahriman.core.upload.github.GitHub.release_get", return_value={})
get_hashes_mock = mocker.patch("ahriman.core.upload.github.GitHub.get_hashes", return_value={})
get_local_files_mock = mocker.patch("ahriman.core.upload.github.GitHub.get_local_files", return_value={})
files_upload_mock = mocker.patch("ahriman.core.upload.github.GitHub.files_upload")
files_remove_mock = mocker.patch("ahriman.core.upload.github.GitHub.files_remove")
release_update_mock = mocker.patch("ahriman.core.upload.github.GitHub.release_update")
github.sync(Path("local"), [])
release_get_mock.assert_called_once_with()
@ -199,17 +216,17 @@ def test_release_sync(github: Github, mocker: MockerFixture) -> None:
release_update_mock.assert_called_once_with({}, pytest.helpers.anyvar(int))
def test_release_sync_create_release(github: Github, mocker: MockerFixture) -> None:
def test_release_sync_create_release(github: GitHub, mocker: MockerFixture) -> None:
"""
must create release in case if it does not exist
"""
mocker.patch("ahriman.core.upload.github.Github.release_get", return_value=None)
mocker.patch("ahriman.core.upload.github.Github.get_hashes")
mocker.patch("ahriman.core.upload.github.Github.get_local_files")
mocker.patch("ahriman.core.upload.github.Github.files_upload")
mocker.patch("ahriman.core.upload.github.Github.files_remove")
mocker.patch("ahriman.core.upload.github.Github.release_update")
release_create_mock = mocker.patch("ahriman.core.upload.github.Github.release_create")
mocker.patch("ahriman.core.upload.github.GitHub.release_get", return_value=None)
mocker.patch("ahriman.core.upload.github.GitHub.get_hashes")
mocker.patch("ahriman.core.upload.github.GitHub.get_local_files")
mocker.patch("ahriman.core.upload.github.GitHub.files_upload")
mocker.patch("ahriman.core.upload.github.GitHub.files_remove")
mocker.patch("ahriman.core.upload.github.GitHub.release_update")
release_create_mock = mocker.patch("ahriman.core.upload.github.GitHub.release_create")
github.sync(Path("local"), [])
release_create_mock.assert_called_once_with()

View File

@ -3,12 +3,32 @@ from pytest_mock import MockerFixture
from typing import Any
from unittest.mock import MagicMock, call as MockCall
from ahriman.core.configuration import Configuration
from ahriman.core.upload.s3 import S3
from ahriman.models.repository_paths import RepositoryPaths
_chunk_size = 8 * 1024 * 1024
def test_object_path(configuration: Configuration, mocker: MockerFixture) -> None:
"""
must correctly read object path
"""
_, repository_id = configuration.check_loaded()
# new-style tree
assert S3(repository_id, configuration, "customs3").object_path == Path("aur-clone/x86_64")
# legacy tree
mocker.patch.object(RepositoryPaths, "_suffix", Path("x86_64"))
assert S3(repository_id, configuration, "customs3").object_path == Path("x86_64")
# user defined prefix
configuration.set_option("customs3", "object_path", "local")
assert S3(repository_id, configuration, "customs3").object_path == Path("local")
def test_calculate_etag_big(resource_path_root: Path) -> None:
"""
must calculate checksum for path which is more than one chunk
@ -38,12 +58,12 @@ def test_files_remove(s3_remote_objects: list[Any]) -> None:
must remove remote objects
"""
local_files = {
Path(item.key): item.e_tag for item in s3_remote_objects if item.key != "x86_64/a"
Path(item.key): item.e_tag for item in s3_remote_objects if item.key != "aur-clone/x86_64/a"
}
remote_objects = {Path(item.key): item for item in s3_remote_objects}
S3.files_remove(local_files, remote_objects)
remote_objects[Path("x86_64/a")].delete.assert_called_once_with()
remote_objects[Path("aur-clone/x86_64/a")].delete.assert_called_once_with()
def test_files_upload(s3: S3, s3_remote_objects: list[Any], mocker: MockerFixture) -> None:
@ -55,9 +75,10 @@ def test_files_upload(s3: S3, s3_remote_objects: list[Any], mocker: MockerFixtur
root = Path("path")
local_files = {
Path(item.key.replace("a", "d")): item.e_tag.replace("b", "d").replace("\"", "")
Path(item.key[:-1] + item.key[-1].replace("a", "d")): item.e_tag.replace("b", "d").replace("\"", "")
for item in s3_remote_objects
}
print(local_files)
remote_objects = {Path(item.key): item for item in s3_remote_objects}
mocker.patch("mimetypes.guess_type", side_effect=mimetype)
@ -67,12 +88,12 @@ def test_files_upload(s3: S3, s3_remote_objects: list[Any], mocker: MockerFixtur
upload_mock.upload_file.assert_has_calls(
[
MockCall(
Filename=str(root / s3.architecture / "b"),
Key=f"{s3.architecture}/{s3.architecture}/b",
Filename=str(root / s3.object_path / "b"),
Key=f"{s3.object_path}/b",
ExtraArgs={"ContentType": "text/html"}),
MockCall(
Filename=str(root / s3.architecture / "d"),
Key=f"{s3.architecture}/{s3.architecture}/d",
Filename=str(root / s3.object_path / "d"),
Key=f"{s3.object_path}/d",
ExtraArgs=None),
],
any_order=True)
@ -91,7 +112,7 @@ def test_get_remote_objects(s3: S3, s3_remote_objects: list[Any]) -> None:
"""
must generate list of remote objects by calling boto3 function
"""
expected = {Path(item.key).relative_to(s3.architecture): item for item in s3_remote_objects}
expected = {Path(item.key).relative_to(s3.object_path): item for item in s3_remote_objects}
s3.bucket = MagicMock()
s3.bucket.objects.filter.return_value = s3_remote_objects

View File

@ -14,8 +14,10 @@ def test_upload_failure(configuration: Configuration, mocker: MockerFixture) ->
must raise SyncFailed on errors
"""
mocker.patch("ahriman.core.upload.rsync.Rsync.sync", side_effect=Exception())
_, repository_id = configuration.check_loaded()
with pytest.raises(SynchronizationError):
Upload.load("x86_64", configuration, "rsync").run(Path("path"), [])
Upload.load(repository_id, configuration, "rsync").run(Path("path"), [])
def test_report_dummy(configuration: Configuration, mocker: MockerFixture) -> None:
@ -24,7 +26,9 @@ def test_report_dummy(configuration: Configuration, mocker: MockerFixture) -> No
"""
mocker.patch("ahriman.models.upload_settings.UploadSettings.from_option", return_value=UploadSettings.Disabled)
upload_mock = mocker.patch("ahriman.core.upload.upload.Upload.sync")
Upload.load("x86_64", configuration, "disabled").run(Path("path"), [])
_, repository_id = configuration.check_loaded()
Upload.load(repository_id, configuration, "disabled").run(Path("path"), [])
upload_mock.assert_called_once_with(Path("path"), [])
@ -33,7 +37,9 @@ def test_upload_rsync(configuration: Configuration, mocker: MockerFixture) -> No
must upload via rsync
"""
upload_mock = mocker.patch("ahriman.core.upload.rsync.Rsync.sync")
Upload.load("x86_64", configuration, "rsync").run(Path("path"), [])
_, repository_id = configuration.check_loaded()
Upload.load(repository_id, configuration, "rsync").run(Path("path"), [])
upload_mock.assert_called_once_with(Path("path"), [])
@ -42,7 +48,9 @@ def test_upload_s3(configuration: Configuration, mocker: MockerFixture) -> None:
must upload via s3
"""
upload_mock = mocker.patch("ahriman.core.upload.s3.S3.sync")
Upload.load("x86_64", configuration, "customs3").run(Path("path"), [])
_, repository_id = configuration.check_loaded()
Upload.load(repository_id, configuration, "customs3").run(Path("path"), [])
upload_mock.assert_called_once_with(Path("path"), [])
@ -50,8 +58,10 @@ def test_upload_github(configuration: Configuration, mocker: MockerFixture) -> N
"""
must upload via github
"""
upload_mock = mocker.patch("ahriman.core.upload.github.Github.sync")
Upload.load("x86_64", configuration, "github").run(Path("path"), [])
upload_mock = mocker.patch("ahriman.core.upload.github.GitHub.sync")
_, repository_id = configuration.check_loaded()
Upload.load(repository_id, configuration, "github").run(Path("path"), [])
upload_mock.assert_called_once_with(Path("path"), [])
@ -62,6 +72,7 @@ def test_upload_ahriman(configuration: Configuration, mocker: MockerFixture) ->
upload_mock = mocker.patch("ahriman.core.upload.remote_service.RemoteService.sync")
configuration.set_option("web", "host", "localhost")
configuration.set_option("web", "port", "8080")
_, repository_id = configuration.check_loaded()
Upload.load("x86_64", configuration, "remote-service").run(Path("path"), [])
Upload.load(repository_id, configuration, "remote-service").run(Path("path"), [])
upload_mock.assert_called_once_with(Path("path"), [])

View File

@ -22,7 +22,8 @@ def test_on_result(configuration: Configuration, mocker: MockerFixture) -> None:
"""
configuration.set_option("upload", "target", "rsync")
run_mock = mocker.patch("ahriman.core.upload.upload.Upload.run")
_, repository_id = configuration.check_loaded()
trigger = UploadTrigger("x86_64", configuration)
trigger = UploadTrigger(repository_id, configuration)
trigger.on_result(Result(), [])
run_mock.assert_called_once_with(configuration.repository_paths.repository, [])

View File

@ -0,0 +1,40 @@
import pytest
from ahriman.models.repository_id import RepositoryId
def test_is_empty() -> None:
"""
must check if repository id is empty or not
"""
assert RepositoryId("", "").is_empty
assert RepositoryId("arch", "").is_empty
assert RepositoryId("", "repo").is_empty
assert not RepositoryId("arch", "repo").is_empty
def test_id() -> None:
"""
must correctly generate id
"""
assert RepositoryId("", "").id == "-"
assert RepositoryId("arch", "repo").id == "arch-repo"
def test_lt() -> None:
"""
must correctly compare instances
"""
assert RepositoryId("x86_64", "a") < RepositoryId("x86_64", "b")
assert RepositoryId("x86_64", "b") > RepositoryId("x86_64", "a")
assert RepositoryId("i686", "a") < RepositoryId("x86_64", "a")
assert RepositoryId("x86_64", "a") > RepositoryId("i686", "a")
def test_lt_invalid() -> None:
"""
must raise ValueError if other is not valid repository id
"""
with pytest.raises(ValueError):
RepositoryId("x86_64", "a") < 42

View File

@ -7,6 +7,7 @@ from unittest.mock import MagicMock, call as MockCall
from ahriman.core.exceptions import PathError
from ahriman.models.package import Package
from ahriman.models.repository_id import RepositoryId
from ahriman.models.repository_paths import RepositoryPaths
@ -26,6 +27,30 @@ def _get_owner(root: Path, same: bool) -> Callable[[Path], tuple[int, int]]:
return lambda path: root_owner if path == root else non_root_owner
def test_suffix(repository_id: RepositoryId, mocker: MockerFixture) -> None:
"""
must correctly define suffix
"""
is_dir_mock = mocker.patch("pathlib.Path.is_dir", autospec=True)
is_dir_mock.return_value = True
instance = RepositoryPaths(Path("root"), repository_id)
assert instance._suffix == Path(repository_id.architecture)
is_dir_mock.return_value = False
instance = RepositoryPaths(Path("root"), repository_id)
assert instance._suffix == Path(repository_id.name) / repository_id.architecture
is_dir_mock.return_value = True
instance = RepositoryPaths(Path("root"), repository_id, _force_current_tree=True)
assert instance._suffix == Path(repository_id.name) / repository_id.architecture
is_dir_mock.assert_has_calls([
MockCall(Path("root") / "repository" / repository_id.architecture),
MockCall(Path("root") / "repository" / repository_id.architecture),
])
def test_root_owner(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
"""
must correctly define root directory owner
@ -36,11 +61,129 @@ def test_root_owner(repository_paths: RepositoryPaths, mocker: MockerFixture) ->
def test_known_architectures(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
"""
must list available directory paths
must list available directory paths /repository/repo/arch
"""
is_dir_mock = mocker.patch("pathlib.Path.is_dir", autospec=True, return_value=True)
iterdir_mock = mocker.patch("pathlib.Path.iterdir", autospec=True, return_value=[Path("i686"), Path("x86_64")])
assert repository_paths.known_architectures(repository_paths.root, repository_paths.repository_id.name) == {
"i686",
"x86_64",
}
iterdir_mock.assert_called_once_with(repository_paths._repository_root / repository_paths.repository_id.name)
is_dir_mock.assert_has_calls([
MockCall(repository_paths._repository_root / repository_paths.repository_id.name),
MockCall(Path("i686")),
MockCall(Path("x86_64")),
])
def test_known_architectures_legacy(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
"""
must list available directory paths /repository/arch
"""
def is_dir(path: Path) -> bool:
return path.name != repository_paths.repository_id.name
is_dir_mock = mocker.patch("pathlib.Path.is_dir", autospec=True, side_effect=is_dir)
iterdir_mock = mocker.patch("pathlib.Path.iterdir", autospec=True, return_value=[Path("i686"), Path("x86_64")])
assert repository_paths.known_architectures(repository_paths.root, repository_paths.repository_id.name) == {
"i686",
"x86_64",
}
iterdir_mock.assert_called_once_with(repository_paths._repository_root)
is_dir_mock.assert_has_calls([
MockCall(repository_paths._repository_root / repository_paths.repository_id.name),
MockCall(repository_paths._repository_root),
MockCall(Path("i686")),
MockCall(Path("x86_64")),
])
def test_known_architectures_legacy_backward(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
"""
must list available directory paths /repository/arch in backward compatibility mode
"""
def is_dir(path: Path) -> bool:
return path.name != repository_paths.repository_id.name
is_dir_mock = mocker.patch("pathlib.Path.is_dir", autospec=True, side_effect=is_dir)
iterdir_mock = mocker.patch("pathlib.Path.iterdir", autospec=True, return_value=[Path("i686"), Path("x86_64")])
assert repository_paths.known_architectures(repository_paths.root) == {"i686", "x86_64"}
iterdir_mock.assert_called_once_with(repository_paths._repository_root)
is_dir_mock.assert_has_calls([
MockCall(repository_paths._repository_root),
MockCall(Path("i686")),
MockCall(Path("x86_64")),
])
def test_known_architectures_empty(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
"""
must return empty architectures if tree is not available
"""
mocker.patch("pathlib.Path.is_dir", return_value=False)
iterdir_mock = mocker.patch("pathlib.Path.iterdir")
repository_paths.known_architectures(repository_paths.root)
iterdir_mock.assert_called_once_with()
# new style
assert not repository_paths.known_architectures(repository_paths.root, repository_paths.repository_id.name)
# legacy mode
assert not repository_paths.known_architectures(repository_paths.root)
iterdir_mock.assert_not_called()
def test_known_repositories(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
"""
must list available directory paths /repository/repo
"""
def iterdir(path: Path) -> list[Path]:
if path == repository_paths._repository_root:
return [Path("repo1"), Path("repo2")]
return [Path("x86_64")]
is_dir_mock = mocker.patch("pathlib.Path.is_dir", autospec=True, return_value=True)
iterdir_mock = mocker.patch("pathlib.Path.iterdir", autospec=True, side_effect=iterdir)
assert repository_paths.known_repositories(repository_paths.root) == {"repo1", "repo2"}
iterdir_mock.assert_has_calls([
MockCall(repository_paths._repository_root),
MockCall(Path("repo1")),
MockCall(Path("repo2")),
])
is_dir_mock.assert_has_calls([
MockCall(repository_paths._repository_root),
MockCall(Path("repo1")),
MockCall(Path("x86_64")),
MockCall(Path("repo2")),
MockCall(Path("x86_64")),
])
def test_known_repositories_legacy(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
"""
must return empty repository list for legacy tree
"""
def is_dir(path: Path) -> bool:
return path == repository_paths._repository_root
mocker.patch("pathlib.Path.is_dir", autospec=True, side_effect=is_dir)
iterdir_mock = mocker.patch("pathlib.Path.iterdir", autospec=True, return_value=[Path("i686"), Path("x86_64")])
assert not repository_paths.known_repositories(repository_paths.root)
iterdir_mock.assert_called_once_with(repository_paths._repository_root)
def test_known_repositories_empty(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
"""
must return empty repositories if tree is not available
"""
mocker.patch("pathlib.Path.is_dir", return_value=False)
iterdir_mock = mocker.patch("pathlib.Path.iterdir")
assert not repository_paths.known_repositories(repository_paths.root)
iterdir_mock.assert_not_called()
def test_owner(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
@ -139,19 +282,29 @@ def test_tree_create(repository_paths: RepositoryPaths, mocker: MockerFixture) -
prop
for prop in dir(repository_paths)
if not prop.startswith("_")
and not prop.endswith("_for")
and prop not in ("architecture",
"chown",
"known_architectures",
"owner",
and not callable(getattr(repository_paths, prop))
and prop not in ("logger_name",
"logger",
"repository_id",
"root",
"root_owner",
"tree_clear",
"tree_create")
"root_owner")
}
mkdir_mock = mocker.patch("pathlib.Path.mkdir")
chown_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.chown")
print(paths)
repository_paths.tree_create()
mkdir_mock.assert_has_calls([MockCall(mode=0o755, parents=True, exist_ok=True) for _ in paths], any_order=True)
chown_mock.assert_has_calls([MockCall(pytest.helpers.anyvar(int)) for _ in paths], any_order=True)
def test_tree_create_skip(mocker: MockerFixture) -> None:
"""
must skip tree creation if repository id is not set
"""
mkdir_mock = mocker.patch("pathlib.Path.mkdir")
repository_paths = RepositoryPaths(Path("local"), RepositoryId("", ""))
repository_paths.tree_create()
mkdir_mock.assert_not_called()

View File

@ -112,7 +112,9 @@ def application(configuration: Configuration, spawner: Spawn, database: SQLite,
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("aiohttp_apispec.setup_aiohttp_apispec")
mocker.patch.object(ahriman.core.auth.helpers, "_has_aiohttp_security", False)
return setup_service("x86_64", configuration, spawner)
_, repository_id = configuration.check_loaded()
return setup_service(repository_id, configuration, spawner)
@pytest.fixture
@ -138,7 +140,8 @@ def application_with_auth(configuration: Configuration, user: User, spawner: Spa
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("aiohttp_apispec.setup_aiohttp_apispec")
mocker.patch.object(ahriman.core.auth.helpers, "_has_aiohttp_security", True)
application = setup_service("x86_64", configuration, spawner)
_, repository_id = configuration.check_loaded()
application = setup_service(repository_id, configuration, spawner)
generated = user.hash_password(application["validator"].salt)
mocker.patch("ahriman.core.database.SQLite.user_get", return_value=generated)
@ -169,7 +172,9 @@ def application_with_debug(configuration: Configuration, user: User, spawner: Sp
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("aiohttp_apispec.setup_aiohttp_apispec")
mocker.patch.object(ahriman.core.auth.helpers, "_has_aiohttp_security", False)
return setup_service("x86_64", configuration, spawner)
_, repository_id = configuration.check_loaded()
return setup_service(repository_id, configuration, spawner)
@pytest.fixture