mirror of
				https://github.com/arcan1s/ahriman.git
				synced 2025-11-03 23:33:41 +00:00 
			
		
		
		
	application tests
This commit is contained in:
		@ -105,8 +105,8 @@ class Application:
 | 
				
			|||||||
            for full_path in filter(package_like, path.iterdir()):
 | 
					            for full_path in filter(package_like, path.iterdir()):
 | 
				
			||||||
                add_archive(full_path)
 | 
					                add_archive(full_path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def add_manual(name: str) -> Path:
 | 
					        def add_manual(src: str) -> Path:
 | 
				
			||||||
            package = Package.load(name, self.repository.pacman, self.config.get("alpm", "aur_url"))
 | 
					            package = Package.load(src, self.repository.pacman, self.config.get("alpm", "aur_url"))
 | 
				
			||||||
            path = self.repository.paths.manual / package.base
 | 
					            path = self.repository.paths.manual / package.base
 | 
				
			||||||
            Task.fetch(path, package.git_url)
 | 
					            Task.fetch(path, package.git_url)
 | 
				
			||||||
            return path
 | 
					            return path
 | 
				
			||||||
@ -121,14 +121,14 @@ class Application:
 | 
				
			|||||||
            dependencies = Package.dependencies(path)
 | 
					            dependencies = Package.dependencies(path)
 | 
				
			||||||
            self.add(dependencies.difference(known_packages), without_dependencies)
 | 
					            self.add(dependencies.difference(known_packages), without_dependencies)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def process_single(name: str) -> None:
 | 
					        def process_single(src: str) -> None:
 | 
				
			||||||
            maybe_path = Path(name)
 | 
					            maybe_path = Path(src)
 | 
				
			||||||
            if maybe_path.is_dir():
 | 
					            if maybe_path.is_dir():
 | 
				
			||||||
                add_directory(maybe_path)
 | 
					                add_directory(maybe_path)
 | 
				
			||||||
            elif maybe_path.is_file():
 | 
					            elif maybe_path.is_file():
 | 
				
			||||||
                add_archive(maybe_path)
 | 
					                add_archive(maybe_path)
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                path = add_manual(name)
 | 
					                path = add_manual(src)
 | 
				
			||||||
                process_dependencies(path)
 | 
					                process_dependencies(path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for name in names:
 | 
					        for name in names:
 | 
				
			||||||
 | 
				
			|||||||
@ -67,8 +67,6 @@ class Lock:
 | 
				
			|||||||
            report to web if enabled
 | 
					            report to web if enabled
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        self.check_user()
 | 
					        self.check_user()
 | 
				
			||||||
        if self.force:
 | 
					 | 
				
			||||||
            self.remove()
 | 
					 | 
				
			||||||
        self.create()
 | 
					        self.create()
 | 
				
			||||||
        self.reporter.update_self(BuildStatusEnum.Building)
 | 
					        self.reporter.update_self(BuildStatusEnum.Building)
 | 
				
			||||||
        return self
 | 
					        return self
 | 
				
			||||||
@ -105,7 +103,7 @@ class Lock:
 | 
				
			|||||||
        if self.path is None:
 | 
					        if self.path is None:
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            self.path.touch(exist_ok=False)
 | 
					            self.path.touch(exist_ok=self.force)
 | 
				
			||||||
        except FileExistsError:
 | 
					        except FileExistsError:
 | 
				
			||||||
            raise DuplicateRun()
 | 
					            raise DuplicateRun()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -151,7 +151,7 @@ class Package:
 | 
				
			|||||||
        """
 | 
					        """
 | 
				
			||||||
        # additional function to remove versions from dependencies
 | 
					        # additional function to remove versions from dependencies
 | 
				
			||||||
        def trim_version(name: str) -> str:
 | 
					        def trim_version(name: str) -> str:
 | 
				
			||||||
            for symbol in ('<', '=', '>'):
 | 
					            for symbol in ("<", "=", ">"):
 | 
				
			||||||
                name = name.split(symbol)[0]
 | 
					                name = name.split(symbol)[0]
 | 
				
			||||||
            return name
 | 
					            return name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										20
									
								
								tests/ahriman/application/conftest.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								tests/ahriman/application/conftest.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					import argparse
 | 
				
			||||||
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from pytest_mock import MockerFixture
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from ahriman.application.application import Application
 | 
				
			||||||
 | 
					from ahriman.application.lock import Lock
 | 
				
			||||||
 | 
					from ahriman.core.configuration import Configuration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@pytest.fixture
 | 
				
			||||||
 | 
					def application(configuration: Configuration, mocker: MockerFixture) -> Application:
 | 
				
			||||||
 | 
					    mocker.patch("pathlib.Path.mkdir")
 | 
				
			||||||
 | 
					    return Application("x86_64", configuration)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@pytest.fixture
 | 
				
			||||||
 | 
					def lock(configuration: Configuration) -> Lock:
 | 
				
			||||||
 | 
					    return Lock(argparse.Namespace(lock=None, force=False, unsafe=False, no_report=True),
 | 
				
			||||||
 | 
					                "x86_64", configuration)
 | 
				
			||||||
							
								
								
									
										0
									
								
								tests/ahriman/application/test_ahriman.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								tests/ahriman/application/test_ahriman.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										237
									
								
								tests/ahriman/application/test_application.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										237
									
								
								tests/ahriman/application/test_application.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,237 @@
 | 
				
			|||||||
 | 
					from pytest_mock import MockerFixture
 | 
				
			||||||
 | 
					from unittest import mock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from ahriman.application.application import Application
 | 
				
			||||||
 | 
					from ahriman.core.tree import Leaf, Tree
 | 
				
			||||||
 | 
					from ahriman.models.package import Package
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_finalize(application: Application, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must report and sync at the last
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    report_mock = mocker.patch("ahriman.application.application.Application.report")
 | 
				
			||||||
 | 
					    sync_mock = mocker.patch("ahriman.application.application.Application.sync")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    application._finalize()
 | 
				
			||||||
 | 
					    report_mock.assert_called_once()
 | 
				
			||||||
 | 
					    sync_mock.assert_called_once()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_get_updates_all(application: Application, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must get updates for all
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    updates_aur_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_aur")
 | 
				
			||||||
 | 
					    updates_manual_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_manual")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    application.get_updates([], no_aur=False, no_manual=False, no_vcs=False, log_fn=print)
 | 
				
			||||||
 | 
					    updates_aur_mock.assert_called_with([], False)
 | 
				
			||||||
 | 
					    updates_manual_mock.assert_called_once()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_get_updates_disabled(application: Application, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must get updates without anything
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    updates_aur_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_aur")
 | 
				
			||||||
 | 
					    updates_manual_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_manual")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    application.get_updates([], no_aur=True, no_manual=True, no_vcs=False, log_fn=print)
 | 
				
			||||||
 | 
					    updates_aur_mock.assert_not_called()
 | 
				
			||||||
 | 
					    updates_manual_mock.assert_not_called()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_get_updates_no_aur(application: Application, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must get updates without aur
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    updates_aur_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_aur")
 | 
				
			||||||
 | 
					    updates_manual_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_manual")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    application.get_updates([], no_aur=True, no_manual=False, no_vcs=False, log_fn=print)
 | 
				
			||||||
 | 
					    updates_aur_mock.assert_not_called()
 | 
				
			||||||
 | 
					    updates_manual_mock.assert_called_once()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_get_updates_no_manual(application: Application, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must get updates without manual
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    updates_aur_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_aur")
 | 
				
			||||||
 | 
					    updates_manual_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_manual")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    application.get_updates([], no_aur=False, no_manual=True, no_vcs=False, log_fn=print)
 | 
				
			||||||
 | 
					    updates_aur_mock.assert_called_with([], False)
 | 
				
			||||||
 | 
					    updates_manual_mock.assert_not_called()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_get_updates_no_vcs(application: Application, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must get updates without VCS
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    updates_aur_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_aur")
 | 
				
			||||||
 | 
					    updates_manual_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_manual")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    application.get_updates([], no_aur=False, no_manual=False, no_vcs=True, log_fn=print)
 | 
				
			||||||
 | 
					    updates_aur_mock.assert_called_with([], True)
 | 
				
			||||||
 | 
					    updates_manual_mock.assert_called_once()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_get_updates_with_filter(application: Application, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must get updates without VCS
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    updates_aur_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_aur")
 | 
				
			||||||
 | 
					    updates_manual_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_manual")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    application.get_updates(["filter"], no_aur=False, no_manual=False, no_vcs=False, log_fn=print)
 | 
				
			||||||
 | 
					    updates_aur_mock.assert_called_with(["filter"], False)
 | 
				
			||||||
 | 
					    updates_manual_mock.assert_called_once()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_add_directory(application: Application, package_ahriman: Package, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must add packages from directory
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    mocker.patch("ahriman.application.application.Application._known_packages", return_value=set())
 | 
				
			||||||
 | 
					    mocker.patch("pathlib.Path.is_dir", return_value=True)
 | 
				
			||||||
 | 
					    iterdir_mock = mocker.patch("pathlib.Path.iterdir",
 | 
				
			||||||
 | 
					                                return_value=[package.filepath for package in package_ahriman.packages.values()])
 | 
				
			||||||
 | 
					    move_mock = mocker.patch("shutil.move")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    application.add([package_ahriman.base], False)
 | 
				
			||||||
 | 
					    iterdir_mock.assert_called_once()
 | 
				
			||||||
 | 
					    move_mock.assert_called_once()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_add_manual(application: Application, package_ahriman: Package, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must add package from AUR
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    mocker.patch("ahriman.application.application.Application._known_packages", return_value=set())
 | 
				
			||||||
 | 
					    mocker.patch("ahriman.models.package.Package.load", return_value=package_ahriman)
 | 
				
			||||||
 | 
					    fetch_mock = mocker.patch("ahriman.core.build_tools.task.Task.fetch")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    application.add([package_ahriman.base], True)
 | 
				
			||||||
 | 
					    fetch_mock.assert_called_once()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_add_manual_with_dependencies(application: Application, package_ahriman: Package,
 | 
				
			||||||
 | 
					                                      mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must add package from AUR with dependencies
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    mocker.patch("ahriman.application.application.Application._known_packages", return_value=set())
 | 
				
			||||||
 | 
					    mocker.patch("ahriman.models.package.Package.load", return_value=package_ahriman)
 | 
				
			||||||
 | 
					    mocker.patch("ahriman.core.build_tools.task.Task.fetch")
 | 
				
			||||||
 | 
					    dependencies_mock = mocker.patch("ahriman.models.package.Package.dependencies")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    application.add([package_ahriman.base], False)
 | 
				
			||||||
 | 
					    dependencies_mock.assert_called_once()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_add_package(application: Application, package_ahriman: Package, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must add package from archive
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    mocker.patch("ahriman.application.application.Application._known_packages", return_value=set())
 | 
				
			||||||
 | 
					    mocker.patch("pathlib.Path.is_file", return_value=True)
 | 
				
			||||||
 | 
					    move_mock = mocker.patch("shutil.move")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    application.add([package_ahriman.base], False)
 | 
				
			||||||
 | 
					    move_mock.assert_called_once()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_clean_build(application: Application, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must clean build directory
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    clear_mock = mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_build")
 | 
				
			||||||
 | 
					    application.clean(False, True, True, True, True)
 | 
				
			||||||
 | 
					    clear_mock.assert_called_once()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_clean_cache(application: Application, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must clean cache directory
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    clear_mock = mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_cache")
 | 
				
			||||||
 | 
					    application.clean(True, False, True, True, True)
 | 
				
			||||||
 | 
					    clear_mock.assert_called_once()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_clean_chroot(application: Application, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must clean chroot directory
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    clear_mock = mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_chroot")
 | 
				
			||||||
 | 
					    application.clean(True, True, False, True, True)
 | 
				
			||||||
 | 
					    clear_mock.assert_called_once()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_clean_manual(application: Application, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must clean manual directory
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    clear_mock = mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_manual")
 | 
				
			||||||
 | 
					    application.clean(True, True, True, False, True)
 | 
				
			||||||
 | 
					    clear_mock.assert_called_once()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_clean_packages(application: Application, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must clean packages directory
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    clear_mock = mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_packages")
 | 
				
			||||||
 | 
					    application.clean(True, True, True, True, False)
 | 
				
			||||||
 | 
					    clear_mock.assert_called_once()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_remove(application: Application, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must remove package
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    executor_mock = mocker.patch("ahriman.core.repository.executor.Executor.process_remove")
 | 
				
			||||||
 | 
					    finalize_mock = mocker.patch("ahriman.application.application.Application._finalize")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    application.remove([])
 | 
				
			||||||
 | 
					    executor_mock.assert_called_once()
 | 
				
			||||||
 | 
					    finalize_mock.assert_called_once()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_report(application: Application, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must generate report
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    executor_mock = mocker.patch("ahriman.core.repository.executor.Executor.process_report")
 | 
				
			||||||
 | 
					    application.report(None)
 | 
				
			||||||
 | 
					    executor_mock.assert_called_once()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_sync(application: Application, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must sync to remote
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    executor_mock = mocker.patch("ahriman.core.repository.executor.Executor.process_sync")
 | 
				
			||||||
 | 
					    application.sync(None)
 | 
				
			||||||
 | 
					    executor_mock.assert_called_once()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_update(application: Application, package_ahriman: Package, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must process package updates
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    paths = [package.filepath for package in package_ahriman.packages.values()]
 | 
				
			||||||
 | 
					    tree = Tree([Leaf(package_ahriman, set())])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    mocker.patch("ahriman.core.tree.Tree.load", return_value=tree)
 | 
				
			||||||
 | 
					    mocker.patch("ahriman.core.repository.repository.Repository.packages_built", return_value=[])
 | 
				
			||||||
 | 
					    build_mock = mocker.patch("ahriman.core.repository.executor.Executor.process_build", return_value=paths)
 | 
				
			||||||
 | 
					    update_mock = mocker.patch("ahriman.core.repository.executor.Executor.process_update")
 | 
				
			||||||
 | 
					    finalize_mock = mocker.patch("ahriman.application.application.Application._finalize")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    application.update([package_ahriman])
 | 
				
			||||||
 | 
					    build_mock.assert_called_once()
 | 
				
			||||||
 | 
					    update_mock.assert_has_calls([mock.call([]), mock.call(paths)])
 | 
				
			||||||
 | 
					    finalize_mock.assert_has_calls([mock.call(), mock.call()])
 | 
				
			||||||
							
								
								
									
										151
									
								
								tests/ahriman/application/test_lock.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								tests/ahriman/application/test_lock.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,151 @@
 | 
				
			|||||||
 | 
					import pytest
 | 
				
			||||||
 | 
					import tempfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					from pytest_mock import MockerFixture
 | 
				
			||||||
 | 
					from unittest import mock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from ahriman.application.lock import Lock
 | 
				
			||||||
 | 
					from ahriman.core.exceptions import DuplicateRun, UnsafeRun
 | 
				
			||||||
 | 
					from ahriman.models.build_status import BuildStatusEnum
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_enter(lock: Lock, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must process with context manager
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    check_user_mock = mocker.patch("ahriman.application.lock.Lock.check_user")
 | 
				
			||||||
 | 
					    remove_mock = mocker.patch("ahriman.application.lock.Lock.remove")
 | 
				
			||||||
 | 
					    create_mock = mocker.patch("ahriman.application.lock.Lock.create")
 | 
				
			||||||
 | 
					    update_status_mock = mocker.patch("ahriman.core.status.client.Client.update_self")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with lock:
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					    check_user_mock.assert_called_once()
 | 
				
			||||||
 | 
					    remove_mock.assert_called_once()
 | 
				
			||||||
 | 
					    create_mock.assert_called_once()
 | 
				
			||||||
 | 
					    update_status_mock.assert_has_calls([
 | 
				
			||||||
 | 
					        mock.call(BuildStatusEnum.Building),
 | 
				
			||||||
 | 
					        mock.call(BuildStatusEnum.Success)
 | 
				
			||||||
 | 
					    ])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_exit_with_exception(lock: Lock, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must process with context manager in case if exception raised
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    mocker.patch("ahriman.application.lock.Lock.check_user")
 | 
				
			||||||
 | 
					    mocker.patch("ahriman.application.lock.Lock.remove")
 | 
				
			||||||
 | 
					    mocker.patch("ahriman.application.lock.Lock.create")
 | 
				
			||||||
 | 
					    update_status_mock = mocker.patch("ahriman.core.status.client.Client.update_self")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with pytest.raises(Exception):
 | 
				
			||||||
 | 
					        with lock:
 | 
				
			||||||
 | 
					            raise Exception()
 | 
				
			||||||
 | 
					    update_status_mock.assert_has_calls([
 | 
				
			||||||
 | 
					        mock.call(BuildStatusEnum.Building),
 | 
				
			||||||
 | 
					        mock.call(BuildStatusEnum.Failed)
 | 
				
			||||||
 | 
					    ])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_check_user(lock: Lock, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must check user correctly
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    stat = Path.cwd().stat()
 | 
				
			||||||
 | 
					    mocker.patch("pathlib.Path.stat", return_value=stat)
 | 
				
			||||||
 | 
					    mocker.patch("os.getuid", return_value=stat.st_uid)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lock.check_user()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_check_user_exception(lock: Lock, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must raise exception if user differs
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    stat = Path.cwd().stat()
 | 
				
			||||||
 | 
					    mocker.patch("pathlib.Path.stat")
 | 
				
			||||||
 | 
					    mocker.patch("os.getuid", return_value=stat.st_uid + 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with pytest.raises(UnsafeRun):
 | 
				
			||||||
 | 
					        lock.check_user()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_check_user_unsafe(lock: Lock) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must skip user check if unsafe flag set
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    lock.unsafe = True
 | 
				
			||||||
 | 
					    lock.check_user()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_create(lock: Lock) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must create lock
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    lock.path = Path(tempfile.mktemp())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lock.create()
 | 
				
			||||||
 | 
					    assert lock.path.is_file()
 | 
				
			||||||
 | 
					    lock.path.unlink()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_create_exception(lock: Lock) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must raise exception if file already exists
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    lock.path = Path(tempfile.mktemp())
 | 
				
			||||||
 | 
					    lock.path.touch()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with pytest.raises(DuplicateRun):
 | 
				
			||||||
 | 
					        lock.create()
 | 
				
			||||||
 | 
					    lock.path.unlink()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_create_skip(lock: Lock, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must skip creating if no file set
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    touch_mock = mocker.patch("pathlib.Path.touch")
 | 
				
			||||||
 | 
					    lock.create()
 | 
				
			||||||
 | 
					    touch_mock.assert_not_called()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_create_unsafe(lock: Lock) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must not raise exception if force flag set
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    lock.force = True
 | 
				
			||||||
 | 
					    lock.path = Path(tempfile.mktemp())
 | 
				
			||||||
 | 
					    lock.path.touch()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lock.create()
 | 
				
			||||||
 | 
					    lock.path.unlink()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_remove(lock: Lock) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must remove lock file
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    lock.path = Path(tempfile.mktemp())
 | 
				
			||||||
 | 
					    lock.path.touch()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lock.remove()
 | 
				
			||||||
 | 
					    assert not lock.path.is_file()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_remove_missing(lock: Lock) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must not fail on lock removal if file is missing
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    lock.path = Path(tempfile.mktemp())
 | 
				
			||||||
 | 
					    lock.remove()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_remove_skip(lock: Lock, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must skip removal if no file set
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    unlink_mock = mocker.patch("pathlib.Path.unlink")
 | 
				
			||||||
 | 
					    lock.remove()
 | 
				
			||||||
 | 
					    unlink_mock.assert_not_called()
 | 
				
			||||||
@ -20,7 +20,7 @@ def test_repo_add(repo: Repo, mocker: MockerFixture) -> None:
 | 
				
			|||||||
    check_output_mock = mocker.patch("ahriman.core.alpm.repo.Repo._check_output")
 | 
					    check_output_mock = mocker.patch("ahriman.core.alpm.repo.Repo._check_output")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    repo.add(Path("path"))
 | 
					    repo.add(Path("path"))
 | 
				
			||||||
    Repo._check_output.assert_called_once()
 | 
					    check_output_mock.assert_called_once()
 | 
				
			||||||
    assert check_output_mock.call_args[0][0] == "repo-add"
 | 
					    assert check_output_mock.call_args[0][0] == "repo-add"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -32,7 +32,7 @@ def test_repo_remove(repo: Repo, mocker: MockerFixture) -> None:
 | 
				
			|||||||
    check_output_mock = mocker.patch("ahriman.core.alpm.repo.Repo._check_output")
 | 
					    check_output_mock = mocker.patch("ahriman.core.alpm.repo.Repo._check_output")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    repo.remove("package", Path("package.pkg.tar.xz"))
 | 
					    repo.remove("package", Path("package.pkg.tar.xz"))
 | 
				
			||||||
    Repo._check_output.assert_called_once()
 | 
					    check_output_mock.assert_called_once()
 | 
				
			||||||
    assert check_output_mock.call_args[0][0] == "repo-remove"
 | 
					    assert check_output_mock.call_args[0][0] == "repo-remove"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -57,8 +57,8 @@ def test_init_with_cache(task_ahriman: Task, mocker: MockerFixture) -> None:
 | 
				
			|||||||
    must copy tree instead of fetch
 | 
					    must copy tree instead of fetch
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    mocker.patch("pathlib.Path.is_dir", return_value=True)
 | 
					    mocker.patch("pathlib.Path.is_dir", return_value=True)
 | 
				
			||||||
    mocker.patch("shutil.copytree")
 | 
					 | 
				
			||||||
    mocker.patch("ahriman.core.build_tools.task.Task.fetch")
 | 
					    mocker.patch("ahriman.core.build_tools.task.Task.fetch")
 | 
				
			||||||
 | 
					    copytree_mock = mocker.patch("shutil.copytree")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    task_ahriman.init(None)
 | 
					    task_ahriman.init(None)
 | 
				
			||||||
    shutil.copytree.assert_called_once()
 | 
					    copytree_mock.assert_called_once()
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
from pathlib import Path
 | 
					 | 
				
			||||||
from pytest_mock import MockerFixture
 | 
					from pytest_mock import MockerFixture
 | 
				
			||||||
from unittest import mock
 | 
					from unittest import mock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -14,10 +13,10 @@ def test_create_tree(repository_paths: RepositoryPaths, mocker: MockerFixture) -
 | 
				
			|||||||
        for prop in dir(repository_paths)
 | 
					        for prop in dir(repository_paths)
 | 
				
			||||||
        if not prop.startswith("_") and prop not in ("architecture", "create_tree", "root")
 | 
					        if not prop.startswith("_") and prop not in ("architecture", "create_tree", "root")
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    mocker.patch("pathlib.Path.mkdir")
 | 
					    mkdir_mock = mocker.patch("pathlib.Path.mkdir")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    repository_paths.create_tree()
 | 
					    repository_paths.create_tree()
 | 
				
			||||||
    Path.mkdir.assert_has_calls(
 | 
					    mkdir_mock.assert_has_calls(
 | 
				
			||||||
        [
 | 
					        [
 | 
				
			||||||
            mock.call(mode=0o755, parents=True, exist_ok=True)
 | 
					            mock.call(mode=0o755, parents=True, exist_ok=True)
 | 
				
			||||||
            for _ in paths
 | 
					            for _ in paths
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user