189 lines
6.5 KiB
Python
189 lines
6.5 KiB
Python
import pytest
|
||
from pydantic import ValidationError
|
||
|
||
from src.core.config import Settings, get_settings
|
||
|
||
SMB_ENV = {
|
||
"OPENBAO__SMB__SMB_HOST": "smb.example",
|
||
"OPENBAO__SMB__SMB_PATH": "share",
|
||
"OPENBAO__SMB__SMB_LOGIN": "user",
|
||
"OPENBAO__SMB__SMB_PASSWORD": "secret",
|
||
}
|
||
|
||
|
||
def _clean_env(monkeypatch):
|
||
"""Убрать из окружения всё, что относится к SMB/NATS-учётным данным и режиму горячей папки."""
|
||
for key in list(SMB_ENV) + ["OPENBAO__NATS__NATS_SEED", "OPENBAO__NATS__NATS_JWT", "SCAN_HOTFOLDER_MODE"]:
|
||
monkeypatch.delenv(key, raising=False)
|
||
|
||
|
||
def test_defaults_local_mode_without_smb_and_nats_credentials(monkeypatch, minimal_env_file):
|
||
_clean_env(monkeypatch)
|
||
|
||
s = get_settings()
|
||
|
||
assert s.SERVICE_NAME == "scan-gateway"
|
||
assert s.NATS_ENABLED is True
|
||
assert s.PUBLISH_RETRIES == 3
|
||
assert s.DONE_CACHE_SIZE == 1000
|
||
assert s.SCAN_HOTFOLDER_MODE == "local"
|
||
assert s.SCAN_INPUT_DIR == "Input"
|
||
assert s.SCAN_OUTPUT_DIR == "Output"
|
||
assert not hasattr(s, "SCAN_TMP_DIR") # служебный каталог только у эмулятора (change hotfolder-direct-write)
|
||
assert s.SCAN_SETTLE_SECONDS == 2
|
||
assert s.SCAN_POLL_SECONDS == 5
|
||
assert s.SCAN_TIMEOUT_SECONDS == 1200
|
||
assert s.SCAN_MAX_INFLIGHT == 4
|
||
assert s.OPENBAO.SMB.SMB_HOST == ""
|
||
assert s.OPENBAO.NATS.NATS_SEED == ""
|
||
assert s.OPENBAO.NATS.NATS_JWT == ""
|
||
assert not hasattr(s.OPENBAO, "DATABASE")
|
||
|
||
|
||
def test_local_mode_requires_hotfolder_path(monkeypatch):
|
||
_clean_env(monkeypatch)
|
||
monkeypatch.setenv("SCAN_HOTFOLDER_PATH", "")
|
||
|
||
with pytest.raises(ValidationError, match="SCAN_HOTFOLDER_PATH"):
|
||
get_settings()
|
||
|
||
|
||
def test_smb_mode_without_smb_block_fails_with_clear_error(monkeypatch):
|
||
_clean_env(monkeypatch)
|
||
monkeypatch.setenv("SCAN_HOTFOLDER_MODE", "smb")
|
||
|
||
with pytest.raises(ValidationError, match="OPENBAO__SMB"):
|
||
get_settings()
|
||
|
||
|
||
def test_smb_mode_with_smb_block_ok(monkeypatch):
|
||
_clean_env(monkeypatch)
|
||
monkeypatch.setenv("SCAN_HOTFOLDER_MODE", "smb")
|
||
for key, value in SMB_ENV.items():
|
||
monkeypatch.setenv(key, value)
|
||
|
||
s = get_settings()
|
||
|
||
assert s.OPENBAO.SMB.SMB_HOST == "smb.example"
|
||
|
||
|
||
def test_settle_seconds_zero_is_allowed(monkeypatch):
|
||
monkeypatch.setenv("SCAN_SETTLE_SECONDS", "0")
|
||
|
||
assert get_settings().SCAN_SETTLE_SECONDS == 0
|
||
|
||
|
||
def test_negative_settle_seconds_rejected(monkeypatch):
|
||
monkeypatch.setenv("SCAN_SETTLE_SECONDS", "-1")
|
||
|
||
with pytest.raises(ValidationError, match="SCAN_SETTLE_SECONDS"):
|
||
get_settings()
|
||
|
||
|
||
def test_legacy_scan_tmp_dir_is_ignored(monkeypatch, minimal_env_file):
|
||
"""Старый `.env` с `SCAN_TMP_DIR` (до change hotfolder-direct-write) не ломает старт: `extra="ignore"`."""
|
||
_clean_env(monkeypatch)
|
||
monkeypatch.setenv("SCAN_TMP_DIR", "Tmp")
|
||
|
||
s = get_settings()
|
||
|
||
assert not hasattr(s, "SCAN_TMP_DIR")
|
||
|
||
|
||
@pytest.mark.parametrize("settle", ["10", "11"])
|
||
def test_settle_not_less_than_timeout_rejected(monkeypatch, settle):
|
||
"""M-4: набор не может настояться за срок, который короче или равен settle — каждое задание давало бы TIMEOUT."""
|
||
monkeypatch.setenv("SCAN_TIMEOUT_SECONDS", "10")
|
||
monkeypatch.setenv("SCAN_SETTLE_SECONDS", settle)
|
||
|
||
with pytest.raises(ValidationError, match="SCAN_SETTLE_SECONDS .* меньше SCAN_TIMEOUT_SECONDS"):
|
||
get_settings()
|
||
|
||
|
||
def test_settle_less_than_timeout_is_allowed(monkeypatch):
|
||
monkeypatch.setenv("SCAN_TIMEOUT_SECONDS", "10")
|
||
monkeypatch.setenv("SCAN_SETTLE_SECONDS", "9.9")
|
||
|
||
assert get_settings().SCAN_SETTLE_SECONDS == 9.9
|
||
|
||
|
||
def test_unknown_hotfolder_mode_rejected(monkeypatch):
|
||
monkeypatch.setenv("SCAN_HOTFOLDER_MODE", "ftp")
|
||
|
||
with pytest.raises(ValidationError):
|
||
get_settings()
|
||
|
||
|
||
def test_env_file_selected_by_env_file_variable(monkeypatch, tmp_path):
|
||
_clean_env(monkeypatch)
|
||
for key in (
|
||
"SCAN_HOTFOLDER_PATH",
|
||
"SCAN_POLL_SECONDS",
|
||
"SERVER__PORT",
|
||
"OPENBAO__NATS__NATS_URL",
|
||
"OPENBAO__MINIO__MINIO_URL",
|
||
"OPENBAO__MINIO__MINIO_ADMIN_LOGIN",
|
||
"OPENBAO__MINIO__MINIO_ADMIN_PASSWORD",
|
||
"OPENBAO__MINIO__MINIO_BUCKET",
|
||
):
|
||
monkeypatch.delenv(key, raising=False)
|
||
env_file = tmp_path / "custom.env"
|
||
env_file.write_text(
|
||
"\n".join(
|
||
[
|
||
"OPENBAO__MINIO__MINIO_URL=minio.test:9000",
|
||
"OPENBAO__MINIO__MINIO_ADMIN_LOGIN=a",
|
||
"OPENBAO__MINIO__MINIO_ADMIN_PASSWORD=b",
|
||
"OPENBAO__MINIO__MINIO_BUCKET=bucket",
|
||
"OPENBAO__NATS__NATS_URL=nats://nats.test:4222",
|
||
"SCAN_HOTFOLDER_PATH=/data/hot",
|
||
"SCAN_POLL_SECONDS=1",
|
||
"SERVER__PORT=8123",
|
||
]
|
||
)
|
||
)
|
||
monkeypatch.setenv("ENV_FILE", str(env_file))
|
||
|
||
s = get_settings()
|
||
|
||
assert s.OPENBAO.MINIO.MINIO_URL == "minio.test:9000"
|
||
assert s.OPENBAO.NATS.NATS_URL == "nats://nats.test:4222"
|
||
assert s.SCAN_HOTFOLDER_PATH == "/data/hot"
|
||
assert s.SCAN_POLL_SECONDS == 1
|
||
assert s.server.PORT == 8123
|
||
|
||
|
||
def test_get_settings_is_cached(monkeypatch):
|
||
assert get_settings() is get_settings()
|
||
assert isinstance(get_settings(), Settings)
|
||
|
||
|
||
def test_env_test_file_loads_for_tests():
|
||
"""pytest.ini выбирает `.env.test`: он должен давать рабочие настройки local-режима с укороченными интервалами."""
|
||
s = get_settings()
|
||
|
||
assert s.SCAN_HOTFOLDER_MODE == "local"
|
||
assert s.SCAN_HOTFOLDER_PATH == "./.hotfolder-test"
|
||
assert s.SCAN_POLL_SECONDS == 0.1
|
||
assert s.SCAN_TIMEOUT_SECONDS == 5
|
||
assert not hasattr(s, "SCAN_TMP_DIR")
|
||
assert s.SCAN_SETTLE_SECONDS == 0 # R-23: тесты воркера не ждут стабилизации набора
|
||
assert s.OPENBAO.MINIO.MINIO_URL == "127.0.0.1:9000"
|
||
assert s.OPENBAO.MINIO.MINIO_SECURE is False
|
||
assert s.OPENBAO.NATS.NATS_URL == "nats://127.0.0.1:4222"
|
||
assert s.OPENBAO.NATS.NATS_SEED == ""
|
||
|
||
|
||
def test_env_example_loads(monkeypatch):
|
||
"""`.env.example` — рабочий dev-набор: Settings читает его без ошибок."""
|
||
monkeypatch.setenv("ENV_FILE", ".env.example")
|
||
|
||
s = get_settings()
|
||
|
||
assert s.SCAN_HOTFOLDER_MODE == "local"
|
||
assert s.SCAN_INPUT_DIR == "Input"
|
||
assert not hasattr(s, "SCAN_TMP_DIR")
|
||
assert s.SCAN_SETTLE_SECONDS == 2
|
||
assert s.OPENBAO.MINIO.MINIO_BUCKET == "arm-ka"
|
||
assert s.OPENBAO.NATS.NATS_JWT == ""
|