from pathlib import Path from lohup.app import Lohup from lohup.config import ConfigError from lohup.logger import BasicLogger, LogLevel from lohup.util import DeepValidator, ValidationFailed import pytest toml1 = """ [settings.globals] """ toml2 = """ [[hooks.before-all]] kind = "???" foo = "bar" [repos.local] kind = "local" path = "{base}/repo" repo-key-file = "{pwfile}" """ toml_vars = """ [settings.globals] foo = "$bar" baz = "1" bag = 2 [repos.local] kind = "local" path = "$foo" repo-key-file = "$unknown" """ class RepoEnvironment: def __init__(self, tmp_path: Path): self.basepath = tmp_path self.log = BasicLogger(level=LogLevel.DEBUG) def write_password(self, value: str = "1") -> Path: pth = self.basepath / "password.txt" pth.write_text("1") return pth def write_config(self, value: str) -> Path: pth = self.basepath / "lohup.toml" pth.write_text(value) return pth def test_error_message(tmp_path): env = RepoEnvironment(tmp_path) path = tmp_path / "lohup.toml" path.write_text(toml1) app = Lohup(config_path=str(path), logger=env.log) msg = "no repositories defined" with pytest.raises(ConfigError, match="Failed to parse TOML config") as exc: app.load() env.log.error(exc.value) cause = exc.value.__cause__ assert isinstance(cause, ValidationFailed) and msg in cause.messages def test_hook_error(tmp_path): env = RepoEnvironment(tmp_path) pwfile = env.write_password() tmp_path.joinpath("repo").mkdir() path = tmp_path / "lohup.toml" path.write_text(toml2.format(base=tmp_path, pwfile=pwfile)) app = Lohup(config_path=path, logger=env.log) msg = "hook: before-all: unsupported kind: ???" with pytest.raises(ConfigError, match="Failed to parse TOML config") as exc: app.load() env.log.error(exc.value) cause = exc.value.__cause__ assert isinstance(cause, ValidationFailed) and msg in cause.messages def test_invalid_vars(tmp_path): env = RepoEnvironment(tmp_path) path = env.write_config(toml_vars) app = Lohup(config_path=str(path), logger=env.log) lines = [ "settings: variable 'foo': nested variables in globals are not allowed", "settings: variable 'bag': invalid type: int, expected string", "repo 'local': read repo-key-file: variable 'unknown' is not defined" ] with pytest.raises(ConfigError, match="Failed to parse TOML config") as exc: app.load() env.log.error(exc.value) cause = exc.value.__cause__ assert isinstance(cause, ValidationFailed) for exc in cause.exceptions: env.log.error(exc.value) assert set(lines) == set(cause.messages) def test_validator(): validator = DeepValidator("testing") with validator.inner("read config") as inner: with inner.inner("key 'foo'") as children: children.error("expected string") res = validator.check() assert isinstance(res, ValidationFailed) assert len(res.messages) == 1, "expected error during validation" assert res.messages[0] == "testing: read config: key 'foo': expected string"