add more tests

This commit is contained in:
Evgenii Alekseev 2021-03-30 01:42:01 +03:00
parent 5003cabeb5
commit 3b93510aad
18 changed files with 311 additions and 24 deletions

View File

@ -30,6 +30,8 @@ class Dump(Handler):
dump config handler dump config handler
""" """
_print = print
@classmethod @classmethod
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, config: Configuration) -> None: def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, config: Configuration) -> None:
""" """
@ -40,7 +42,7 @@ class Dump(Handler):
""" """
config_dump = config.dump(architecture) config_dump = config.dump(architecture)
for section, values in sorted(config_dump.items()): for section, values in sorted(config_dump.items()):
print(f"[{section}]") Dump._print(f"[{section}]")
for key, value in sorted(values.items()): for key, value in sorted(values.items()):
print(f"{key} = {value}") Dump._print(f"{key} = {value}")
print() Dump._print()

View File

@ -25,7 +25,7 @@ from typing import Dict, Iterable, List, Optional
from ahriman.core.build_tools.task import Task from ahriman.core.build_tools.task import Task
from ahriman.core.report.report import Report from ahriman.core.report.report import Report
from ahriman.core.repository.cleaner import Cleaner from ahriman.core.repository.cleaner import Cleaner
from ahriman.core.upload.uploader import Uploader from ahriman.core.upload.upload import Upload
from ahriman.models.package import Package from ahriman.models.package import Package
@ -118,7 +118,7 @@ class Executor(Cleaner):
if targets is None: if targets is None:
targets = self.config.getlist("upload", "target") targets = self.config.getlist("upload", "target")
for target in targets: for target in targets:
Uploader.run(self.architecture, self.config, target, self.paths.repository) Upload.run(self.architecture, self.config, target, self.paths.repository)
def process_update(self, packages: Iterable[Path]) -> Path: def process_update(self, packages: Iterable[Path]) -> Path:
""" """

View File

@ -20,11 +20,11 @@
from pathlib import Path from pathlib import Path
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.upload.uploader import Uploader from ahriman.core.upload.upload import Upload
from ahriman.core.util import check_output from ahriman.core.util import check_output
class Rsync(Uploader): class Rsync(Upload):
""" """
rsync wrapper rsync wrapper
:ivar remote: remote address to sync :ivar remote: remote address to sync
@ -38,7 +38,7 @@ class Rsync(Uploader):
:param architecture: repository architecture :param architecture: repository architecture
:param config: configuration instance :param config: configuration instance
""" """
Uploader.__init__(self, architecture, config) Upload.__init__(self, architecture, config)
section = config.get_section_name("rsync", architecture) section = config.get_section_name("rsync", architecture)
self.remote = config.get(section, "remote") self.remote = config.get(section, "remote")

View File

@ -20,11 +20,11 @@
from pathlib import Path from pathlib import Path
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.upload.uploader import Uploader from ahriman.core.upload.upload import Upload
from ahriman.core.util import check_output from ahriman.core.util import check_output
class S3(Uploader): class S3(Upload):
""" """
aws-cli wrapper aws-cli wrapper
:ivar bucket: full bucket name :ivar bucket: full bucket name
@ -38,7 +38,7 @@ class S3(Uploader):
:param architecture: repository architecture :param architecture: repository architecture
:param config: configuration instance :param config: configuration instance
""" """
Uploader.__init__(self, architecture, config) Upload.__init__(self, architecture, config)
section = config.get_section_name("s3", architecture) section = config.get_section_name("s3", architecture)
self.bucket = config.get(section, "bucket") self.bucket = config.get(section, "bucket")

View File

@ -26,7 +26,7 @@ from ahriman.core.exceptions import SyncFailed
from ahriman.models.upload_settings import UploadSettings from ahriman.models.upload_settings import UploadSettings
class Uploader: class Upload:
""" """
base remote sync class base remote sync class
:ivar architecture: repository architecture :ivar architecture: repository architecture
@ -56,17 +56,17 @@ class Uploader:
provider = UploadSettings.from_option(target) provider = UploadSettings.from_option(target)
if provider == UploadSettings.Rsync: if provider == UploadSettings.Rsync:
from ahriman.core.upload.rsync import Rsync from ahriman.core.upload.rsync import Rsync
uploader: Uploader = Rsync(architecture, config) upload: Upload = Rsync(architecture, config)
elif provider == UploadSettings.S3: elif provider == UploadSettings.S3:
from ahriman.core.upload.s3 import S3 from ahriman.core.upload.s3 import S3
uploader = S3(architecture, config) upload = S3(architecture, config)
else: else:
uploader = Uploader(architecture, config) upload = Upload(architecture, config)
try: try:
uploader.sync(path) upload.sync(path)
except Exception: except Exception:
uploader.logger.exception(f"remote sync failed for {provider.name}") upload.logger.exception(f"remote sync failed for {provider.name}")
raise SyncFailed() raise SyncFailed()
def sync(self, path: Path) -> None: def sync(self, path: Path) -> None:

View File

@ -31,7 +31,7 @@ from typing import Any, Dict, List, Optional, Set, Type, Union
from ahriman.core.alpm.pacman import Pacman from ahriman.core.alpm.pacman import Pacman
from ahriman.core.exceptions import InvalidPackageInfo from ahriman.core.exceptions import InvalidPackageInfo
from ahriman.core.util import check_output from ahriman.core.util import check_output
from ahriman.models.package_desciption import PackageDescription from ahriman.models.package_description import PackageDescription
from ahriman.models.repository_paths import RepositoryPaths from ahriman.models.repository_paths import RepositoryPaths

View File

@ -11,7 +11,10 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
must run command must run command
""" """
mocker.patch("pathlib.Path.mkdir") mocker.patch("pathlib.Path.mkdir")
application_mock = mocker.patch("ahriman.core.configuration.Configuration.dump") print_mock = mocker.patch("ahriman.application.handlers.dump.Dump._print")
application_mock = mocker.patch("ahriman.core.configuration.Configuration.dump",
return_value=configuration.dump("x86_64"))
Dump.run(args, "x86_64", configuration) Dump.run(args, "x86_64", configuration)
application_mock.assert_called_once() application_mock.assert_called_once()
print_mock.assert_called()

View File

@ -7,7 +7,7 @@ from typing import Any, Type, TypeVar
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.status.watcher import Watcher from ahriman.core.status.watcher import Watcher
from ahriman.models.package import Package from ahriman.models.package import Package
from ahriman.models.package_desciption import PackageDescription from ahriman.models.package_description import PackageDescription
from ahriman.models.repository_paths import RepositoryPaths from ahriman.models.repository_paths import RepositoryPaths
T = TypeVar("T") T = TypeVar("T")

View File

@ -0,0 +1,16 @@
from pytest_mock import MockerFixture
from ahriman.core.configuration import Configuration
from ahriman.core.report.html import HTML
from ahriman.models.package import Package
def test_generate(configuration: Configuration, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must generate report
"""
write_mock = mocker.patch("pathlib.Path.write_text")
report = HTML("x86_64", configuration)
report.generate([package_ahriman])
write_mock.assert_called_once()

View File

@ -0,0 +1,27 @@
import pytest
from pathlib import Path
from pytest_mock import MockerFixture
from ahriman.core.configuration import Configuration
from ahriman.core.exceptions import ReportFailed
from ahriman.core.report.report import Report
from ahriman.models.report_settings import ReportSettings
def test_report_failure(configuration: Configuration, mocker: MockerFixture) -> None:
"""
must raise ReportFailed on errors
"""
mocker.patch("ahriman.core.report.html.HTML.generate", side_effect=Exception())
with pytest.raises(ReportFailed):
Report.run("x86_64", configuration, ReportSettings.HTML.name, Path("path"))
def test_report_html(configuration: Configuration, mocker: MockerFixture) -> None:
"""
must generate html report
"""
report_mock = mocker.patch("ahriman.core.report.html.HTML.generate")
Report.run("x86_64", configuration, ReportSettings.HTML.name, Path("path"))
report_mock.assert_called_once()

View File

@ -0,0 +1,16 @@
from pathlib import Path
from pytest_mock import MockerFixture
from ahriman.core.configuration import Configuration
from ahriman.core.upload.rsync import Rsync
def test_sync(configuration: Configuration, mocker: MockerFixture) -> None:
"""
must run sync command
"""
check_output_mock = mocker.patch("ahriman.core.upload.rsync.Rsync._check_output")
upload = Rsync("x86_64", configuration)
upload.sync(Path("path"))
check_output_mock.assert_called_once()

View File

@ -0,0 +1,16 @@
from pathlib import Path
from pytest_mock import MockerFixture
from ahriman.core.configuration import Configuration
from ahriman.core.upload.s3 import S3
def test_sync(configuration: Configuration, mocker: MockerFixture) -> None:
"""
must run sync command
"""
check_output_mock = mocker.patch("ahriman.core.upload.s3.S3._check_output")
upload = S3("x86_64", configuration)
upload.sync(Path("path"))
check_output_mock.assert_called_once()

View File

@ -0,0 +1,36 @@
import pytest
from pathlib import Path
from pytest_mock import MockerFixture
from ahriman.core.configuration import Configuration
from ahriman.core.exceptions import SyncFailed
from ahriman.core.upload.upload import Upload
from ahriman.models.upload_settings import UploadSettings
def test_upload_failure(configuration: Configuration, mocker: MockerFixture) -> None:
"""
must raise SyncFailed on errors
"""
mocker.patch("ahriman.core.upload.rsync.Rsync.sync", side_effect=Exception())
with pytest.raises(SyncFailed):
Upload.run("x86_64", configuration, UploadSettings.Rsync.name, Path("path"))
def test_upload_rsync(configuration: Configuration, mocker: MockerFixture) -> None:
"""
must upload via rsync
"""
upload_mock = mocker.patch("ahriman.core.upload.rsync.Rsync.sync")
Upload.run("x86_64", configuration, UploadSettings.Rsync.name, Path("path"))
upload_mock.assert_called_once()
def test_upload_s3(configuration: Configuration, mocker: MockerFixture) -> None:
"""
must upload via s3
"""
upload_mock = mocker.patch("ahriman.core.upload.s3.S3.sync")
Upload.run("x86_64", configuration, UploadSettings.S3.name, Path("path"))
upload_mock.assert_called_once()

View File

@ -1,8 +1,10 @@
import pytest import pytest
from unittest.mock import MagicMock, PropertyMock
from ahriman.models.build_status import BuildStatus, BuildStatusEnum from ahriman.models.build_status import BuildStatus, BuildStatusEnum
from ahriman.models.package import Package from ahriman.models.package import Package
from ahriman.models.package_desciption import PackageDescription from ahriman.models.package_description import PackageDescription
@pytest.fixture @pytest.fixture
@ -17,3 +19,33 @@ def package_tpacpi_bat_git() -> Package:
version="3.1.r12.g4959b52-1", version="3.1.r12.g4959b52-1",
aur_url="https://aur.archlinux.org", aur_url="https://aur.archlinux.org",
packages={"tpacpi-bat-git": PackageDescription()}) packages={"tpacpi-bat-git": PackageDescription()})
@pytest.fixture
def pyalpm_handle(pyalpm_package_ahriman: MagicMock) -> MagicMock:
mock = MagicMock()
mock.handle.load_pkg.return_value = pyalpm_package_ahriman
return mock
@pytest.fixture
def pyalpm_package_ahriman(package_ahriman: Package) -> MagicMock:
mock = MagicMock()
type(mock).base = PropertyMock(return_value=package_ahriman.base)
type(mock).name = PropertyMock(return_value=package_ahriman.base)
type(mock).version = PropertyMock(return_value=package_ahriman.version)
return mock
@pytest.fixture
def pyalpm_package_description_ahriman(package_description_ahriman: PackageDescription) -> MagicMock:
mock = MagicMock()
type(mock).arch = PropertyMock(return_value=package_description_ahriman.architecture)
type(mock).builddate = PropertyMock(return_value=package_description_ahriman.build_date)
type(mock).desc = PropertyMock(return_value=package_description_ahriman.description)
type(mock).groups = PropertyMock(return_value=package_description_ahriman.groups)
type(mock).isize = PropertyMock(return_value=package_description_ahriman.installed_size)
type(mock).licenses = PropertyMock(return_value=package_description_ahriman.licenses)
type(mock).size = PropertyMock(return_value=package_description_ahriman.archive_size)
type(mock).url = PropertyMock(return_value=package_description_ahriman.url)
return mock

View File

@ -1,6 +1,10 @@
import pytest
from pathlib import Path from pathlib import Path
from pytest_mock import MockerFixture from pytest_mock import MockerFixture
from unittest.mock import MagicMock, PropertyMock
from ahriman.core.exceptions import InvalidPackageInfo
from ahriman.models.package import Package from ahriman.models.package import Package
from ahriman.models.repository_paths import RepositoryPaths from ahriman.models.repository_paths import RepositoryPaths
@ -72,6 +76,44 @@ def test_web_url(package_ahriman: Package) -> None:
assert package_ahriman.base in package_ahriman.web_url assert package_ahriman.base in package_ahriman.web_url
def test_from_archive(package_ahriman: Package, pyalpm_handle: MagicMock, mocker: MockerFixture) -> None:
"""
must construct package from alpm library
"""
mocker.patch("ahriman.models.package_description.PackageDescription.from_package",
return_value=package_ahriman.packages[package_ahriman.base])
assert Package.from_archive(Path("path"), pyalpm_handle, package_ahriman.aur_url) == package_ahriman
def test_from_aur(package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must construct package from aur
"""
mock = MagicMock()
type(mock).name = PropertyMock(return_value=package_ahriman.base)
type(mock).package_base = PropertyMock(return_value=package_ahriman.base)
type(mock).version = PropertyMock(return_value=package_ahriman.version)
mocker.patch("aur.info", return_value=mock)
package = Package.from_aur(package_ahriman.base, package_ahriman.aur_url)
assert package_ahriman.base == package.base
assert package_ahriman.version == package.version
assert package_ahriman.packages.keys() == package.packages.keys()
def test_from_build(package_ahriman: Package, mocker: MockerFixture, resource_path_root: Path) -> None:
"""
must construct package from srcinfo
"""
srcinfo = (resource_path_root / "models" / "package_ahriman_srcinfo").read_text()
mocker.patch("pathlib.Path.read_text", return_value=srcinfo)
package = Package.from_build(Path("path"), package_ahriman.aur_url)
assert package_ahriman.packages.keys() == package.packages.keys()
package_ahriman.packages = package.packages # we are not going to test PackageDescription here
assert package_ahriman == package
def test_from_json_view_1(package_ahriman: Package) -> None: def test_from_json_view_1(package_ahriman: Package) -> None:
""" """
must construct same object from json must construct same object from json
@ -98,12 +140,64 @@ def test_dependencies_with_version(mocker: MockerFixture, resource_path_root: Pa
must load correct list of dependencies with version must load correct list of dependencies with version
""" """
srcinfo = (resource_path_root / "models" / "package_yay_srcinfo").read_text() srcinfo = (resource_path_root / "models" / "package_yay_srcinfo").read_text()
mocker.patch("pathlib.Path.read_text", return_value=srcinfo) mocker.patch("pathlib.Path.read_text", return_value=srcinfo)
assert Package.dependencies(Path("path")) == {"git", "go", "pacman"} assert Package.dependencies(Path("path")) == {"git", "go", "pacman"}
def test_full_version() -> None:
"""
must construct full version
"""
assert Package.full_version("1", "r2388.d30e3201", "1") == "1:r2388.d30e3201-1"
assert Package.full_version(None, "0.12.1", "1") == "0.12.1-1"
def test_load_from_archive(package_ahriman: Package, pyalpm_handle: MagicMock, mocker: MockerFixture) -> None:
"""
must load package from package archive
"""
mocker.patch("pathlib.Path.is_file", return_value=True)
load_mock = mocker.patch("ahriman.models.package.Package.from_archive")
Package.load(Path("path"), pyalpm_handle, package_ahriman.aur_url)
load_mock.assert_called_once()
def test_load_from_aur(package_ahriman: Package, pyalpm_handle: MagicMock, mocker: MockerFixture) -> None:
"""
must load package from AUR
"""
load_mock = mocker.patch("ahriman.models.package.Package.from_aur")
Package.load(Path("path"), pyalpm_handle, package_ahriman.aur_url)
load_mock.assert_called_once()
def test_load_from_build(package_ahriman: Package, pyalpm_handle: MagicMock, mocker: MockerFixture) -> None:
"""
must load package from build directory
"""
mocker.patch("pathlib.Path.is_dir", return_value=True)
load_mock = mocker.patch("ahriman.models.package.Package.from_build")
Package.load(Path("path"), pyalpm_handle, package_ahriman.aur_url)
load_mock.assert_called_once()
def test_load_failure(package_ahriman: Package, pyalpm_handle: MagicMock, mocker: MockerFixture) -> None:
"""
must raise InvalidPackageInfo on exception
"""
mocker.patch("pathlib.Path.is_dir", side_effect=InvalidPackageInfo("exception!"))
with pytest.raises(InvalidPackageInfo):
Package.load(Path("path"), pyalpm_handle, package_ahriman.aur_url)
mocker.patch("pathlib.Path.is_dir", side_effect=Exception())
with pytest.raises(InvalidPackageInfo):
Package.load(Path("path"), pyalpm_handle, package_ahriman.aur_url)
def test_actual_version(package_ahriman: Package, repository_paths: RepositoryPaths) -> None: def test_actual_version(package_ahriman: Package, repository_paths: RepositoryPaths) -> None:
""" """
must return same actual_version as version is must return same actual_version as version is
@ -117,7 +211,6 @@ def test_actual_version_vcs(package_tpacpi_bat_git: Package, repository_paths: R
must return valid actual_version for VCS package must return valid actual_version for VCS package
""" """
srcinfo = (resource_path_root / "models" / "package_tpacpi-bat-git_srcinfo").read_text() srcinfo = (resource_path_root / "models" / "package_tpacpi-bat-git_srcinfo").read_text()
mocker.patch("ahriman.models.package.Package._check_output", return_value=srcinfo) mocker.patch("ahriman.models.package.Package._check_output", return_value=srcinfo)
mocker.patch("ahriman.core.build_tools.task.Task.fetch") mocker.patch("ahriman.core.build_tools.task.Task.fetch")

View File

@ -1,4 +1,6 @@
from ahriman.models.package_desciption import PackageDescription from unittest.mock import MagicMock
from ahriman.models.package_description import PackageDescription
def test_filepath(package_description_ahriman: PackageDescription) -> None: def test_filepath(package_description_ahriman: PackageDescription) -> None:
@ -15,3 +17,13 @@ def test_filepath_empty(package_description_ahriman: PackageDescription) -> None
""" """
package_description_ahriman.filename = None package_description_ahriman.filename = None
assert package_description_ahriman.filepath is None assert package_description_ahriman.filepath is None
def test_from_package(package_description_ahriman: PackageDescription,
pyalpm_package_description_ahriman: MagicMock) -> None:
"""
must construct description from package object
"""
package_description = PackageDescription.from_package(pyalpm_package_description_ahriman,
package_description_ahriman.filepath)
assert package_description_ahriman == package_description

View File

@ -0,0 +1,34 @@
pkgbase = ahriman
pkgdesc = ArcHlinux ReposItory MANager
pkgver = 0.12.1
pkgrel = 1
url = https://github.com/arcan1s/ahriman
arch = any
license = GPL3
makedepends = python-pip
depends = devtools
depends = git
depends = pyalpm
depends = python-aur
depends = python-srcinfo
optdepends = aws-cli: sync to s3
optdepends = breezy: -bzr packages support
optdepends = darcs: -darcs packages support
optdepends = gnupg: package and repository sign
optdepends = mercurial: -hg packages support
optdepends = python-aiohttp: web server
optdepends = python-aiohttp-jinja2: web server
optdepends = python-jinja: html report generation
optdepends = python-requests: web server
optdepends = rsync: sync by using rsync
optdepends = subversion: -svn packages support
backup = etc/ahriman.ini
backup = etc/ahriman.ini.d/logging.ini
source = https://github.com/arcan1s/ahriman/releases/download/0.12.1/ahriman-0.12.1-src.tar.xz
source = ahriman.sysusers
source = ahriman.tmpfiles
sha512sums = 8acc57f937d587ca665c29092cadddbaf3ba0b80e870b80d1551e283aba8f21306f9030a26fec8c71ab5863316f5f5f061b7ddc63cdff9e6d5a885f28ef1893d
sha512sums = 13718afec2c6786a18f0b223ef8e58dccf0688bca4cdbe203f14071f5031ed20120eb0ce38b52c76cfd6e8b6581a9c9eaa2743eb11abbaca637451a84c33f075
sha512sums = 55b20f6da3d66e7bbf2add5d95a3b60632df121717d25a993e56e737d14f51fe063eb6f1b38bd81cc32e05db01c0c1d80aaa720c45cde87f238d8b46cdb8cbc4
pkgname = ahriman