Тестирование
Локальные проверки
python -m unittest discover -s tests -p 'test_*.py' -v
python tests/integration.py prepare
python tests/integration.py bootstrap
python tests/integration.py prepare
python tests/integration.py configure
python tests/integration.py up
python tests/integration.py check
python tests/integration.py down
Integration fixture использует project smtp-integration, отдельные named volumes, тестовый домен example.test и loopback-порты 19025/19587/19993/19443/19444. Никакие реальные внешние письма не отправляются; внешние сценарии завершаются на RCPT. Команда down удаляет только тестовые volumes этого project.
Тест проверяет локальную доставку через IMAP, external-out deny/allow, external-in deny/allow, отсутствие AUTH на 25, open relay и подмену MAIL FROM. NAS preflight тестируется отдельно; named volume не подменяет проверку настоящего NFS.
На целевом сервере
Пройдите все пункты приёмки, включая перезагрузку хоста с NAS, отказ запуска без NAS, восстановление backup и внешнюю доставку через SMTP2GO с SPF/DKIM/DMARC. Не выдавайте результаты Docker Desktop за проверку OMV/NFS, WAN или реального лимита RAM под нагрузкой.
Полный тест Linux-установщика
docker build -t smtp-host-test -f tests/Dockerfile .
docker volume create mail_test_nas_hybrid
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
-v /var/lib/docker/volumes:/var/lib/docker/volumes \
-v "$PWD:/repo:ro" -v mail_test_nas_hybrid:/mail-test-nas \
-e NAS_VOLUME=mail_test_nas_hybrid smtp-host-test /repo/tests/host_smoke.py
docker volume rm mail_test_nas_hybrid
Запускайте на тестовом Docker daemon со стандартным data-root /var/lib/docker: fixture получает Docker socket и доступ к volumes. Он создаёт два уникальных локальных state volumes и удаляет их после проверки. NAS эмулируется отдельным volume: Python audit hook запрещает root открывать и менять его файлы, а настоящие права 0700 проверяют доступ процесса Stalwart с UID 1000. Проверка физического NFS заменена заглушкой. Setup, владельцы файлов, секреты, TLS, SMTP, Roundcube login, изменение relay через рабочий HTTPS API, pg_dump и pg_restore выполняются настоящими скриптами. Порты хоста не публикуются.
Проверено при разработке
- 24 unit tests на Linux: NAS fail-closed, прямой NFS и NFS под autofs, смена UID и проверка marker, разделение локального state и NAS, отложенный/активный relay, сохранение SMTP credentials, отсутствие автоматических bind-каталогов, портов bootstrap и Docker restart, ошибки backup/restore (включая возобновление сервисов при недоступном NAS), защита от выхода archive paths за target, права восстановленного портала, ссылки документации, изоляция proxy-сетей и разделение nginx-конфигураций.
- Bash syntax и компиляция Python.
- Bootstrap API, настройка PostgreSQL/filesystem, RCPT ACL и TLS на Stalwart 0.16.21.
- Roundcube 1.7.4: вход в настоящий ящик через HTTPS с проверкой CA и CSRF.
- SMTP allow/deny matrix, отказ relay и spoofing, локальная доставка с чтением по IMAP.
- Сохранность исходного письма после пересоздания контейнеров; запуск на PostgreSQL 17.11 и nginx 1.30.4.
- Визуально проверен портал в браузере; для локального статического preview использован HTTP без секретов. TLS trust ОС/браузера не изменялся.
- Linux installer: локальный Docker volume с PostgreSQL subpath, NAS только для blobs/backup с UID 1000, реальные владельцы файлов, права 0600, локальная CA, повторный setup без сброса, создание backup и восстановление двух БД в новый локальный volume и пустой NAS-каталог.
- После восстановления: все четыре сервиса healthy; исходный ящик и исходное письмо повторно прочитаны через IMAP.
Физический OMV/NFS, systemd boot и отправка через реальные SMTP2GO credentials здесь не проверялись.
HomeMaster / proxy
python tests/proxy_smoke.py
Не запускайте одновременно с integration.py: используется один тестовый проект smtp-integration. Проверка создаёт собственные сети вместо настоящих proxy / homelab_internal_proxy, и удаляет только тестовый проект с его volumes в конце.
Проверены настоящий bootstrap и SMTP/IMAP, вход в Roundcube из публичной сети, 404 на публичных /admin и /jmap, недоступность DNS-имён private services из публичной сети, отсутствие listener 8444 на web, работа отдельного admin-шлюза с проверяемым upstream TLS. HTTP-клиенты имитируют upstream-соединения двух NPM. Настоящие HomeMaster, NPM, их сертификаты и доступ с WAN/VPN должны быть проверены на сервере пользователя.
Отложенный SMTP2GO
python tests/deferred_relay_smoke.py
Проверка поднимает Stalwart без SMTP2GO credentials, убеждается в отсутствии relay route, создаёт ящик receive, принимает для него внешний RCPT и отклоняет исходящий внешний RCPT после AUTH. Использует тот же тестовый проект, поэтому запускается отдельно от других integration smoke tests.