mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-24 15:27:17 +00:00
complete core tests
This commit is contained in:
parent
46fb33bb9a
commit
0f3741d5f4
@ -102,7 +102,7 @@ class Application:
|
||||
known_packages = self._known_packages()
|
||||
|
||||
def add_directory(path: Path) -> None:
|
||||
for full_path in filter(lambda p: package_like(p.name), path.iterdir()):
|
||||
for full_path in filter(package_like, path.iterdir()):
|
||||
add_archive(full_path)
|
||||
|
||||
def add_manual(name: str) -> Path:
|
||||
@ -192,8 +192,7 @@ class Application:
|
||||
process_update(packages)
|
||||
|
||||
# process manual packages
|
||||
tree = Tree()
|
||||
tree.load(updates)
|
||||
tree = Tree.load(updates)
|
||||
for num, level in enumerate(tree.levels()):
|
||||
self.logger.info(f"processing level #{num} {[package.base for package in level]}")
|
||||
packages = self.repository.process_build(level)
|
||||
|
@ -55,7 +55,8 @@ class Configuration(configparser.RawConfigParser):
|
||||
"""
|
||||
:return: path to directory with configuration includes
|
||||
"""
|
||||
return Path(self.get("settings", "include"))
|
||||
value = Path(self.get("settings", "include"))
|
||||
return self.absolute_path_for(value)
|
||||
|
||||
@classmethod
|
||||
def from_path(cls: Type[Configuration], path: Path, logfile: bool) -> Configuration:
|
||||
@ -70,6 +71,16 @@ class Configuration(configparser.RawConfigParser):
|
||||
config.load_logging(logfile)
|
||||
return config
|
||||
|
||||
def absolute_path_for(self, path_part: Path) -> Path:
|
||||
"""
|
||||
helper to generate absolute configuration path for relative settings value
|
||||
:param path_part: path to generate
|
||||
:return: absolute path according to current path configuration
|
||||
"""
|
||||
if self.path is None or path_part.is_absolute():
|
||||
return path_part
|
||||
return self.path.parent / path_part
|
||||
|
||||
def dump(self, architecture: str) -> Dict[str, Dict[str, str]]:
|
||||
"""
|
||||
dump configuration to dictionary
|
||||
@ -137,8 +148,10 @@ class Configuration(configparser.RawConfigParser):
|
||||
"""
|
||||
def file_logger() -> None:
|
||||
try:
|
||||
fileConfig(self.get("settings", "logging"))
|
||||
except PermissionError:
|
||||
value = Path(self.get("settings", "logging"))
|
||||
config_path = self.absolute_path_for(value)
|
||||
fileConfig(config_path)
|
||||
except (FileNotFoundError, PermissionError):
|
||||
console_logger()
|
||||
logging.exception("could not create logfile, fallback to stderr")
|
||||
|
||||
|
@ -38,7 +38,7 @@ class Repository(Executor, UpdateHandler):
|
||||
"""
|
||||
result: Dict[str, Package] = {}
|
||||
for full_path in self.paths.repository.iterdir():
|
||||
if not package_like(full_path.name):
|
||||
if not package_like(full_path):
|
||||
continue
|
||||
try:
|
||||
local = Package.load(full_path, self.pacman, self.aur_url)
|
||||
|
@ -23,7 +23,7 @@ import shutil
|
||||
import tempfile
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Iterable, List, Set
|
||||
from typing import Iterable, List, Set, Type
|
||||
|
||||
from ahriman.core.build_tools.task import Task
|
||||
from ahriman.models.package import Package
|
||||
@ -36,13 +36,14 @@ class Leaf:
|
||||
:ivar package: leaf package properties
|
||||
"""
|
||||
|
||||
def __init__(self, package: Package) -> None:
|
||||
def __init__(self, package: Package, dependencies: Set[str]) -> None:
|
||||
"""
|
||||
default constructor
|
||||
:param package: package properties
|
||||
:param dependencies: package dependencies
|
||||
"""
|
||||
self.package = package
|
||||
self.dependencies: Set[str] = set()
|
||||
self.dependencies = dependencies
|
||||
|
||||
@property
|
||||
def items(self) -> Iterable[str]:
|
||||
@ -51,6 +52,21 @@ class Leaf:
|
||||
"""
|
||||
return self.package.packages.keys()
|
||||
|
||||
@classmethod
|
||||
def load(cls: Type[Leaf], package: Package) -> Leaf:
|
||||
"""
|
||||
load leaf from package with dependencies
|
||||
:param package: package properties
|
||||
:return: loaded class
|
||||
"""
|
||||
clone_dir = Path(tempfile.mkdtemp())
|
||||
try:
|
||||
Task.fetch(clone_dir, package.git_url)
|
||||
dependencies = Package.dependencies(clone_dir)
|
||||
finally:
|
||||
shutil.rmtree(clone_dir, ignore_errors=True)
|
||||
return cls(package, dependencies)
|
||||
|
||||
def is_root(self, packages: Iterable[Leaf]) -> bool:
|
||||
"""
|
||||
check if package depends on any other package from list of not
|
||||
@ -62,17 +78,6 @@ class Leaf:
|
||||
return False
|
||||
return True
|
||||
|
||||
def load_dependencies(self) -> None:
|
||||
"""
|
||||
load dependencies for the leaf
|
||||
"""
|
||||
clone_dir = Path(tempfile.mkdtemp())
|
||||
try:
|
||||
Task.fetch(clone_dir, self.package.git_url)
|
||||
self.dependencies = Package.dependencies(clone_dir)
|
||||
finally:
|
||||
shutil.rmtree(clone_dir, ignore_errors=True)
|
||||
|
||||
|
||||
class Tree:
|
||||
"""
|
||||
@ -80,11 +85,21 @@ class Tree:
|
||||
:ivar leaves: list of tree leaves
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
def __init__(self, leaves: List[Leaf]) -> None:
|
||||
"""
|
||||
default constructor
|
||||
:param leaves: leaves to build the tree
|
||||
"""
|
||||
self.leaves: List[Leaf] = []
|
||||
self.leaves = leaves
|
||||
|
||||
@classmethod
|
||||
def load(cls: Type[Tree], packages: Iterable[Package]) -> Tree:
|
||||
"""
|
||||
load tree from packages
|
||||
:param packages: packages list
|
||||
:return: loaded class
|
||||
"""
|
||||
return cls([Leaf.load(package) for package in packages])
|
||||
|
||||
def levels(self) -> List[List[Package]]:
|
||||
"""
|
||||
@ -99,13 +114,3 @@ class Tree:
|
||||
unprocessed = [leaf for leaf in unprocessed if not leaf.is_root(unprocessed)]
|
||||
|
||||
return result
|
||||
|
||||
def load(self, packages: Iterable[Package]) -> None:
|
||||
"""
|
||||
load tree from packages
|
||||
:param packages: packages list
|
||||
"""
|
||||
for package in packages:
|
||||
leaf = Leaf(package)
|
||||
leaf.load_dependencies()
|
||||
self.leaves.append(leaf)
|
||||
|
@ -28,19 +28,17 @@ from ahriman.core.exceptions import InvalidOption
|
||||
|
||||
|
||||
def check_output(*args: str, exception: Optional[Exception],
|
||||
cwd: Optional[Path] = None, stderr: int = subprocess.STDOUT,
|
||||
logger: Optional[Logger] = None) -> str:
|
||||
cwd: Optional[Path] = None, logger: Optional[Logger] = None) -> str:
|
||||
"""
|
||||
subprocess wrapper
|
||||
:param args: command line arguments
|
||||
:param exception: exception which has to be reraised instead of default subprocess exception
|
||||
:param cwd: current working directory
|
||||
:param stderr: standard error output mode
|
||||
:param logger: logger to log command result if required
|
||||
:return: command output
|
||||
"""
|
||||
try:
|
||||
result = subprocess.check_output(args, cwd=cwd, stderr=stderr).decode("utf8").strip()
|
||||
result = subprocess.check_output(args, cwd=cwd, stderr=subprocess.STDOUT).decode("utf8").strip()
|
||||
if logger is not None:
|
||||
for line in result.splitlines():
|
||||
logger.debug(line)
|
||||
@ -52,13 +50,14 @@ def check_output(*args: str, exception: Optional[Exception],
|
||||
return result
|
||||
|
||||
|
||||
def package_like(filename: str) -> bool:
|
||||
def package_like(filename: Path) -> bool:
|
||||
"""
|
||||
check if file looks like package
|
||||
:param filename: name of file to check
|
||||
:return: True in case if name contains `.pkg.` and not signature, False otherwise
|
||||
"""
|
||||
return ".pkg." in filename and not filename.endswith(".sig")
|
||||
name = filename.name
|
||||
return ".pkg." in name and not name.endswith(".sig")
|
||||
|
||||
|
||||
def pretty_datetime(timestamp: Optional[int]) -> str:
|
||||
@ -86,10 +85,10 @@ def pretty_size(size: Optional[float], level: int = 0) -> str:
|
||||
return "MiB"
|
||||
if level == 3:
|
||||
return "GiB"
|
||||
raise InvalidOption(level) # I hope it will not be more than 1024 GiB
|
||||
raise InvalidOption(level) # must never happen actually
|
||||
|
||||
if size is None:
|
||||
return ""
|
||||
if size < 1024:
|
||||
return f"{round(size, 2)} {str_level()}"
|
||||
if size < 1024 or level == 3:
|
||||
return f"{size:.1f} {str_level()}"
|
||||
return pretty_size(size / 1024, level + 1)
|
||||
|
@ -18,6 +18,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
|
||||
@ -35,3 +36,10 @@ class PackageDescription:
|
||||
build_date: Optional[int] = None
|
||||
filename: Optional[str] = None
|
||||
installed_size: Optional[int] = None
|
||||
|
||||
@property
|
||||
def filepath(self) -> Optional[Path]:
|
||||
"""
|
||||
:return: path object for current filename
|
||||
"""
|
||||
return Path(self.filename) if self.filename is not None else None
|
||||
|
@ -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
|
Loading…
Reference in New Issue
Block a user