add config validator subcommand (#80)

* add config validator subcommand

* add --exit-code flag

* docs & faq update
This commit is contained in:
2023-01-09 17:22:29 +02:00
committed by GitHub
parent 1f07a89316
commit d942a70272
36 changed files with 1393 additions and 47 deletions

View File

@ -0,0 +1,19 @@
import pytest
from ahriman.core.configuration import Configuration
from ahriman.core.configuration.schema import CONFIGURATION_SCHEMA
from ahriman.core.configuration.validator import Validator
@pytest.fixture
def validator(configuration: Configuration) -> Validator:
"""
fixture for validator
Args:
configuration(Configuration): configuration fixture
Returns:
Validator: validator test instance
"""
return Validator(instance=configuration, schema=CONFIGURATION_SCHEMA)

View File

@ -0,0 +1,70 @@
from pathlib import Path
from pytest_mock import MockerFixture
from unittest.mock import MagicMock
from ahriman.core.configuration.validator import Validator
def test_types_mapping() -> None:
"""
must set custom types
"""
assert "path" in Validator.types_mapping
assert Path in Validator.types_mapping["path"].included_types
def test_normalize_coerce_absolute_path(validator: Validator) -> None:
"""
must convert string value to path by using configuration converters
"""
convert_mock = MagicMock()
validator.instance.converters["path"] = convert_mock
validator._normalize_coerce_absolute_path("value")
convert_mock.assert_called_once_with("value")
def test_normalize_coerce_boolean(validator: Validator, mocker: MockerFixture) -> None:
"""
must convert string value to boolean by using configuration converters
"""
convert_mock = mocker.patch("ahriman.core.configuration.Configuration._convert_to_boolean")
validator._normalize_coerce_boolean("1")
convert_mock.assert_called_once_with("1")
def test_normalize_coerce_integer(validator: Validator) -> None:
"""
must convert string value to integer by using configuration converters
"""
assert validator._normalize_coerce_integer("1") == 1
assert validator._normalize_coerce_integer("42") == 42
def test_normalize_coerce_list(validator: Validator) -> None:
"""
must convert string value to list by using configuration converters
"""
convert_mock = MagicMock()
validator.instance.converters["list"] = convert_mock
validator._normalize_coerce_list("value")
convert_mock.assert_called_once_with("value")
def test_validate_path_exists(validator: Validator, mocker: MockerFixture) -> None:
"""
must validate that paths exists
"""
error_mock = mocker.patch("ahriman.core.configuration.validator.Validator._error")
mocker.patch("pathlib.Path.exists", return_value=False)
validator._validate_path_exists(False, "field", Path("1"))
mocker.patch("pathlib.Path.exists", return_value=False)
validator._validate_path_exists(True, "field", Path("2"))
mocker.patch("pathlib.Path.exists", return_value=True)
validator._validate_path_exists(True, "field", Path("3"))
error_mock.assert_called_once_with("field", "Path 2 must exist")

View File

@ -1,7 +1,7 @@
import pytest
from ahriman.core.formatters import AurPrinter, ConfigurationPrinter, PackagePrinter, PatchPrinter, StatusPrinter, \
StringPrinter, TreePrinter, UpdatePrinter, UserPrinter, VersionPrinter
StringPrinter, TreePrinter, UpdatePrinter, UserPrinter, ValidationPrinter, VersionPrinter
from ahriman.models.aur_package import AURPackage
from ahriman.models.build_status import BuildStatus
from ahriman.models.package import Package
@ -126,6 +126,29 @@ def user_printer(user: User) -> UserPrinter:
return UserPrinter(user)
@pytest.fixture
def validation_printer() -> ValidationPrinter:
"""
fixture for validation printer
Returns:
ValidationPrinter: validation printer test instance
"""
return ValidationPrinter("root", [
"root error",
{
"child": [
"child error",
{
"grandchild": [
"grandchild error",
],
},
],
},
])
@pytest.fixture
def version_printer(package_ahriman: Package) -> VersionPrinter:
"""

View File

@ -1,7 +1,9 @@
from unittest.mock import MagicMock
from pytest_mock import MockerFixture
from unittest.mock import MagicMock, call as MockCall
from ahriman.core.formatters import PackagePrinter
from ahriman.core.formatters import Printer
from ahriman.models.property import Property
def test_print(package_ahriman_printer: PackagePrinter) -> None:
@ -31,6 +33,24 @@ def test_print_verbose(package_ahriman_printer: PackagePrinter) -> None:
log_mock.assert_called()
def test_print_indent(mocker: MockerFixture) -> None:
"""
must correctly use indentation
"""
log_mock = MagicMock()
mocker.patch("ahriman.core.formatters.Printer.properties", return_value=[Property("key", "value", indent=0)])
Printer().print(verbose=True, log_fn=log_mock)
mocker.patch("ahriman.core.formatters.Printer.properties", return_value=[Property("key", "value", indent=1)])
Printer().print(verbose=True, log_fn=log_mock)
mocker.patch("ahriman.core.formatters.Printer.properties", return_value=[Property("key", "value", indent=2)])
Printer().print(verbose=True, log_fn=log_mock)
log_mock.assert_has_calls([MockCall("key: value"), MockCall("\tkey: value"), MockCall("\t\tkey: value")])
def test_properties() -> None:
"""
must return empty properties list

View File

@ -0,0 +1,28 @@
from ahriman.core.formatters import ValidationPrinter
from ahriman.models.property import Property
def test_properties(validation_printer: ValidationPrinter) -> None:
"""
must return non-empty properties list
"""
assert validation_printer.properties()
def test_title(validation_printer: ValidationPrinter) -> None:
"""
must return non-empty title
"""
assert validation_printer.title() is not None
def test_get_error_messages(validation_printer: ValidationPrinter) -> None:
"""
must get error messages from plain list
"""
result = ValidationPrinter.get_error_messages(validation_printer.node, validation_printer.errors)
assert list(result) == [
Property("root", "root error", is_required=True, indent=1),
Property("child", "child error", is_required=True, indent=2),
Property("grandchild", "grandchild error", is_required=True, indent=3),
]