mirror of
				https://github.com/arcan1s/ahriman.git
				synced 2025-11-03 23:33:41 +00:00 
			
		
		
		
	complete core tests
This commit is contained in:
		@ -6,6 +6,7 @@ from ahriman.core.alpm.pacman import Pacman
 | 
			
		||||
from ahriman.core.alpm.repo import Repo
 | 
			
		||||
from ahriman.core.build_tools.task import Task
 | 
			
		||||
from ahriman.core.configuration import Configuration
 | 
			
		||||
from ahriman.core.tree import Leaf
 | 
			
		||||
from ahriman.models.package import Package
 | 
			
		||||
from ahriman.models.repository_paths import RepositoryPaths
 | 
			
		||||
 | 
			
		||||
@ -16,6 +17,16 @@ def configuration(resource_path_root: Path) -> Configuration:
 | 
			
		||||
    return Configuration.from_path(path=path, logfile=False)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def leaf_ahriman(package_ahriman: Package) -> Leaf:
 | 
			
		||||
    return Leaf(package_ahriman, set())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def leaf_python_schedule(package_python_schedule: Package) -> Leaf:
 | 
			
		||||
    return Leaf(package_python_schedule, set())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def pacman(configuration: Configuration) -> Pacman:
 | 
			
		||||
    return Pacman(configuration)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										127
									
								
								tests/ahriman/core/test_configuration.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								tests/ahriman/core/test_configuration.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,127 @@
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
 | 
			
		||||
from pytest_mock import MockerFixture
 | 
			
		||||
 | 
			
		||||
from ahriman.core.configuration import Configuration
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_from_path(mocker: MockerFixture) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must load configuration
 | 
			
		||||
    """
 | 
			
		||||
    read_mock = mocker.patch("configparser.RawConfigParser.read")
 | 
			
		||||
    load_includes_mock = mocker.patch("ahriman.core.configuration.Configuration.load_includes")
 | 
			
		||||
    load_logging_mock = mocker.patch("ahriman.core.configuration.Configuration.load_logging")
 | 
			
		||||
    path = Path("path")
 | 
			
		||||
 | 
			
		||||
    config = Configuration.from_path(path, True)
 | 
			
		||||
    assert config.path == path
 | 
			
		||||
    read_mock.assert_called_with(path)
 | 
			
		||||
    load_includes_mock.assert_called_once()
 | 
			
		||||
    load_logging_mock.assert_called_once()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_absolute_path_for_absolute(configuration: Configuration) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must not change path for absolute path in settings
 | 
			
		||||
    """
 | 
			
		||||
    path = Path("/a/b/c")
 | 
			
		||||
    assert configuration.absolute_path_for(path) == path
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_absolute_path_for_relative(configuration: Configuration) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must prepend root path to relative path
 | 
			
		||||
    """
 | 
			
		||||
    path = Path("a")
 | 
			
		||||
    result = configuration.absolute_path_for(path)
 | 
			
		||||
    assert result.is_absolute()
 | 
			
		||||
    assert result.parent == configuration.path.parent
 | 
			
		||||
    assert result.name == path.name
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_dump(configuration: Configuration) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    dump must not be empty
 | 
			
		||||
    """
 | 
			
		||||
    assert configuration.dump("x86_64")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_dump_architecture_specific(configuration: Configuration) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    dump must contain architecture specific settings
 | 
			
		||||
    """
 | 
			
		||||
    configuration.add_section("build_x86_64")
 | 
			
		||||
    configuration.set("build_x86_64", "archbuild_flags", "")
 | 
			
		||||
 | 
			
		||||
    dump = configuration.dump("x86_64")
 | 
			
		||||
    assert dump
 | 
			
		||||
    assert "build" not in dump
 | 
			
		||||
    assert "build_x86_64" in dump
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_getlist(configuration: Configuration) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must return list of string correctly
 | 
			
		||||
    """
 | 
			
		||||
    configuration.set("build", "test_list", "a b c")
 | 
			
		||||
    assert configuration.getlist("build", "test_list") == ["a", "b", "c"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_getlist_empty(configuration: Configuration) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must return list of string correctly for non-existing option
 | 
			
		||||
    """
 | 
			
		||||
    assert configuration.getlist("build", "test_list") == []
 | 
			
		||||
    configuration.set("build", "test_list", "")
 | 
			
		||||
    assert configuration.getlist("build", "test_list") == []
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_getlist_single(configuration: Configuration) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must return list of strings for single string
 | 
			
		||||
    """
 | 
			
		||||
    configuration.set("build", "test_list", "a")
 | 
			
		||||
    assert configuration.getlist("build", "test_list") == ["a"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_get_section_name(configuration: Configuration) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must return architecture specific group
 | 
			
		||||
    """
 | 
			
		||||
    configuration.add_section("build_x86_64")
 | 
			
		||||
    configuration.set("build_x86_64", "archbuild_flags", "")
 | 
			
		||||
    assert configuration.get_section_name("build", "x86_64") == "build_x86_64"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_get_section_name_missing(configuration: Configuration) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must return default group if architecture depending group does not exist
 | 
			
		||||
    """
 | 
			
		||||
    assert configuration.get_section_name("prefix", "suffix") == "prefix"
 | 
			
		||||
    assert configuration.get_section_name("build", "x86_64") == "build"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_load_includes_missing(configuration: Configuration) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must not fail if not include directory found
 | 
			
		||||
    """
 | 
			
		||||
    configuration.set("settings", "include", "path")
 | 
			
		||||
    configuration.load_includes()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_load_logging_fallback(configuration: Configuration, mocker: MockerFixture) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must fallback to stderr without errors
 | 
			
		||||
    """
 | 
			
		||||
    mocker.patch("logging.config.fileConfig", side_effect=PermissionError())
 | 
			
		||||
    configuration.load_logging(True)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_load_logging_stderr(configuration: Configuration, mocker: MockerFixture) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must use stderr if flag set
 | 
			
		||||
    """
 | 
			
		||||
    logging_mock = mocker.patch("logging.config.fileConfig")
 | 
			
		||||
    configuration.load_logging(False)
 | 
			
		||||
    logging_mock.assert_not_called()
 | 
			
		||||
							
								
								
									
										78
									
								
								tests/ahriman/core/test_tree.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								tests/ahriman/core/test_tree.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,78 @@
 | 
			
		||||
from pytest_mock import MockerFixture
 | 
			
		||||
 | 
			
		||||
from ahriman.core.tree import Leaf, Tree
 | 
			
		||||
from ahriman.models.package import Package
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_leaf_is_root_empty(leaf_ahriman: Leaf) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must be root for empty packages list
 | 
			
		||||
    """
 | 
			
		||||
    assert leaf_ahriman.is_root([])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_leaf_is_root_false(leaf_ahriman: Leaf, leaf_python_schedule: Leaf) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must be root for empty dependencies list or if does not depend on packages
 | 
			
		||||
    """
 | 
			
		||||
    assert leaf_ahriman.is_root([leaf_python_schedule])
 | 
			
		||||
    leaf_ahriman.dependencies = {"ahriman-dependency"}
 | 
			
		||||
    assert leaf_ahriman.is_root([leaf_python_schedule])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_leaf_is_root_true(leaf_ahriman: Leaf, leaf_python_schedule: Leaf) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must not be root if depends on packages
 | 
			
		||||
    """
 | 
			
		||||
    leaf_ahriman.dependencies = {"python-schedule"}
 | 
			
		||||
    assert not leaf_ahriman.is_root([leaf_python_schedule])
 | 
			
		||||
 | 
			
		||||
    leaf_ahriman.dependencies = {"python2-schedule"}
 | 
			
		||||
    assert not leaf_ahriman.is_root([leaf_python_schedule])
 | 
			
		||||
 | 
			
		||||
    leaf_ahriman.dependencies = set(leaf_python_schedule.package.packages.keys())
 | 
			
		||||
    assert not leaf_ahriman.is_root([leaf_python_schedule])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_leaf_load(package_ahriman: Package, mocker: MockerFixture) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must load with dependencies
 | 
			
		||||
    """
 | 
			
		||||
    tempdir_mock = mocker.patch("tempfile.mkdtemp")
 | 
			
		||||
    fetch_mock = mocker.patch("ahriman.core.build_tools.task.Task.fetch")
 | 
			
		||||
    dependencies_mock = mocker.patch("ahriman.models.package.Package.dependencies", return_value={"ahriman-dependency"})
 | 
			
		||||
    rmtree_mock = mocker.patch("shutil.rmtree")
 | 
			
		||||
 | 
			
		||||
    leaf = Leaf.load(package_ahriman)
 | 
			
		||||
    assert leaf.package == package_ahriman
 | 
			
		||||
    assert leaf.dependencies == {"ahriman-dependency"}
 | 
			
		||||
    tempdir_mock.assert_called_once()
 | 
			
		||||
    fetch_mock.assert_called_once()
 | 
			
		||||
    dependencies_mock.assert_called_once()
 | 
			
		||||
    rmtree_mock.assert_called_once()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_tree_levels(leaf_ahriman: Leaf, leaf_python_schedule: Leaf, mocker: MockerFixture) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must generate correct levels in the simples case
 | 
			
		||||
    """
 | 
			
		||||
    leaf_ahriman.dependencies = set(leaf_python_schedule.package.packages.keys())
 | 
			
		||||
 | 
			
		||||
    tree = Tree([leaf_ahriman, leaf_python_schedule])
 | 
			
		||||
    assert len(tree.levels()) == 2
 | 
			
		||||
    first, second = tree.levels()
 | 
			
		||||
    assert first == [leaf_python_schedule.package]
 | 
			
		||||
    assert second == [leaf_ahriman.package]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_tree_load(package_ahriman: Package, package_python_schedule: Package, mocker: MockerFixture) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must package list
 | 
			
		||||
    """
 | 
			
		||||
    mocker.patch("tempfile.mkdtemp")
 | 
			
		||||
    mocker.patch("ahriman.core.build_tools.task.Task.fetch")
 | 
			
		||||
    mocker.patch("ahriman.models.package.Package.dependencies")
 | 
			
		||||
    mocker.patch("shutil.rmtree")
 | 
			
		||||
 | 
			
		||||
    tree = Tree.load([package_ahriman, package_python_schedule])
 | 
			
		||||
    assert len(tree.leaves) == 2
 | 
			
		||||
							
								
								
									
										131
									
								
								tests/ahriman/core/test_util.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								tests/ahriman/core/test_util.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,131 @@
 | 
			
		||||
import logging
 | 
			
		||||
import pytest
 | 
			
		||||
import subprocess
 | 
			
		||||
 | 
			
		||||
from pytest_mock import MockerFixture
 | 
			
		||||
 | 
			
		||||
from ahriman.core.util import check_output, package_like, pretty_datetime, pretty_size
 | 
			
		||||
from ahriman.models.package import Package
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_check_output(mocker: MockerFixture) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must run command and log result
 | 
			
		||||
    """
 | 
			
		||||
    logger_mock = mocker.patch("logging.Logger.debug")
 | 
			
		||||
 | 
			
		||||
    assert check_output("echo", "hello", exception=None) == "hello"
 | 
			
		||||
    logger_mock.assert_not_called()
 | 
			
		||||
 | 
			
		||||
    assert check_output("echo", "hello", exception=None, logger=logging.getLogger("")) == "hello"
 | 
			
		||||
    logger_mock.assert_called_once()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_check_output_failure(mocker: MockerFixture) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must process exception correctly
 | 
			
		||||
    """
 | 
			
		||||
    logger_mock = mocker.patch("logging.Logger.debug")
 | 
			
		||||
    mocker.patch("subprocess.check_output", side_effect=subprocess.CalledProcessError(1, "echo"))
 | 
			
		||||
 | 
			
		||||
    with pytest.raises(subprocess.CalledProcessError):
 | 
			
		||||
        check_output("echo", "hello", exception=None)
 | 
			
		||||
        logger_mock.assert_not_called()
 | 
			
		||||
 | 
			
		||||
    with pytest.raises(subprocess.CalledProcessError):
 | 
			
		||||
        check_output("echo", "hello", exception=None, logger=logging.getLogger(""))
 | 
			
		||||
        logger_mock.assert_not_called()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_check_output_failure_log(mocker: MockerFixture) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must process exception correctly and log it
 | 
			
		||||
    """
 | 
			
		||||
    logger_mock = mocker.patch("logging.Logger.debug")
 | 
			
		||||
    mocker.patch("subprocess.check_output", side_effect=subprocess.CalledProcessError(1, "echo", output=b"result"))
 | 
			
		||||
 | 
			
		||||
    with pytest.raises(subprocess.CalledProcessError):
 | 
			
		||||
        check_output("echo", "hello", exception=None, logger=logging.getLogger(""))
 | 
			
		||||
        logger_mock.assert_called_once()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_package_like(package_ahriman: Package) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    package_like must return true for archives
 | 
			
		||||
    """
 | 
			
		||||
    assert package_like(package_ahriman.packages[package_ahriman.base].filepath)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_package_like_sig(package_ahriman: Package) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    package_like must return false for signature files
 | 
			
		||||
    """
 | 
			
		||||
    package_file = package_ahriman.packages[package_ahriman.base].filepath
 | 
			
		||||
    sig_file = package_file.parent / f"{package_file.name}.sig"
 | 
			
		||||
    assert not package_like(sig_file)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_pretty_datetime() -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must generate string from timestamp value
 | 
			
		||||
    """
 | 
			
		||||
    assert pretty_datetime(0) == "1970-01-01 00:00:00"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_pretty_datetime_empty() -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must generate empty string from None timestamp
 | 
			
		||||
    """
 | 
			
		||||
    assert pretty_datetime(None) == ""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_pretty_size_bytes() -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must generate bytes string for bytes value
 | 
			
		||||
    """
 | 
			
		||||
    value, abbrev = pretty_size(42).split()
 | 
			
		||||
    assert value == "42.0"
 | 
			
		||||
    assert abbrev == "B"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_pretty_size_kbytes() -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must generate kibibytes string for kibibytes value
 | 
			
		||||
    """
 | 
			
		||||
    value, abbrev = pretty_size(42 * 1024).split()
 | 
			
		||||
    assert value == "42.0"
 | 
			
		||||
    assert abbrev == "KiB"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_pretty_size_mbytes() -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must generate mebibytes string for mebibytes value
 | 
			
		||||
    """
 | 
			
		||||
    value, abbrev = pretty_size(42 * 1024 * 1024).split()
 | 
			
		||||
    assert value == "42.0"
 | 
			
		||||
    assert abbrev == "MiB"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_pretty_size_gbytes() -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must generate gibibytes string for gibibytes value
 | 
			
		||||
    """
 | 
			
		||||
    value, abbrev = pretty_size(42 * 1024 * 1024 * 1024).split()
 | 
			
		||||
    assert value == "42.0"
 | 
			
		||||
    assert abbrev == "GiB"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_pretty_size_pbytes() -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must generate pebibytes string for pebibytes value
 | 
			
		||||
    """
 | 
			
		||||
    value, abbrev = pretty_size(42 * 1024 * 1024 * 1024 * 1024).split()
 | 
			
		||||
    assert value == "43008.0"
 | 
			
		||||
    assert abbrev == "GiB"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_pretty_size_empty() -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must generate empty string for None value
 | 
			
		||||
    """
 | 
			
		||||
    assert pretty_size(None) == ""
 | 
			
		||||
@ -0,0 +1,17 @@
 | 
			
		||||
from ahriman.models.package_desciption import PackageDescription
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_filepath(package_description_ahriman: PackageDescription) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must generate correct filepath if set
 | 
			
		||||
    """
 | 
			
		||||
    assert package_description_ahriman.filepath is not None
 | 
			
		||||
    assert package_description_ahriman.filepath.name == package_description_ahriman.filename
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_filepath_empty(package_description_ahriman: PackageDescription) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    must return None for missing filename
 | 
			
		||||
    """
 | 
			
		||||
    package_description_ahriman.filename = None
 | 
			
		||||
    assert package_description_ahriman.filepath is None
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user