"""Проверки генерации Caddyfile и запуска.""" from app.launcher import MARK, ensure_caddyfile, render_caddyfile class TestRender: def test_domains_go_into_site_block(self): text = render_caddyfile("a.example.com, b.example.com", 8756, 500) assert "a.example.com, b.example.com {" in text def test_extra_spaces_and_empty_entries_are_dropped(self): text = render_caddyfile(" a.example.com ,, b.example.com ,", 8756, 500) assert "a.example.com, b.example.com {" in text def test_port_and_limit_come_from_settings(self): text = render_caddyfile("a.example.com", 9000, 250) assert "reverse_proxy 127.0.0.1:9000" in text assert "max_size 250MB" in text def test_real_client_address_is_forwarded(self): """Без этого заголовка список разрешённых адресов увидит localhost.""" text = render_caddyfile("a.example.com", 8756, 500) assert "header_up X-Forwarded-For {remote_host}" in text def test_caddy_log_goes_to_file(self): """Иначе Caddy забивает консоль сообщениями про сертификаты.""" text = render_caddyfile("a.example.com", 8756, 500) assert "output file logs/caddy.log" in text def test_generated_file_is_marked(self): assert render_caddyfile("a.example.com", 8756, 500).startswith(MARK) class TestEnsure: def test_creates_file_when_missing(self, tmp_path): content = render_caddyfile("a.example.com", 8756, 500) written = ensure_caddyfile(tmp_path, content) assert written == tmp_path / "Caddyfile" assert written.read_text(encoding="utf-8") == content def test_overwrites_own_previous_version(self, tmp_path): ensure_caddyfile(tmp_path, render_caddyfile("old.example.com", 8756, 500)) fresh = render_caddyfile("new.example.com", 8756, 500) ensure_caddyfile(tmp_path, fresh) assert (tmp_path / "Caddyfile").read_text(encoding="utf-8") == fresh assert not (tmp_path / "Caddyfile.new").exists() def test_keeps_hand_written_file(self, tmp_path): """Чужой файл не трогаем: молча стереть настройку хуже, чем оставить старую.""" handmade = "site.example.com {\n\treverse_proxy 127.0.0.1:1234\n}\n" (tmp_path / "Caddyfile").write_text(handmade, encoding="utf-8") written = ensure_caddyfile(tmp_path, render_caddyfile("a.example.com", 8756, 500)) assert (tmp_path / "Caddyfile").read_text(encoding="utf-8") == handmade assert written == tmp_path / "Caddyfile.new" assert MARK in written.read_text(encoding="utf-8") def test_no_rewrite_when_nothing_changed(self, tmp_path): content = render_caddyfile("a.example.com", 8756, 500) ensure_caddyfile(tmp_path, content) before = (tmp_path / "Caddyfile").stat().st_mtime_ns assert ensure_caddyfile(tmp_path, content) is None assert (tmp_path / "Caddyfile").stat().st_mtime_ns == before class TestStartupOrder: def test_updater_runs_before_service(self, tmp_path, monkeypatch): """Обновиться нужно до запуска, иначе обновление бессмысленно.""" import app.launcher as launcher calls: list[str] = [] class FakeSettings: base_dir = tmp_path port = 8756 max_upload_mb = 500 https_domains = "" monkeypatch.setattr("app.config.load_settings", lambda: FakeSettings()) monkeypatch.setattr("app.updater.main", lambda: calls.append("updater")) monkeypatch.setitem( __import__("sys").modules, "app.main", type("M", (), {"run": staticmethod(lambda: calls.append("run"))})) assert launcher.main([]) == 0 assert calls == ["updater", "run"] def test_https_without_domains_stops_with_explanation(self, tmp_path, monkeypatch): """Пустые домены - это ошибка настройки, а не повод падать внутри Caddy.""" import app.launcher as launcher class FakeSettings: base_dir = tmp_path port = 8756 max_upload_mb = 500 https_domains = " " monkeypatch.setattr("app.config.load_settings", lambda: FakeSettings()) monkeypatch.setattr("app.updater.main", lambda: None) assert launcher.main(["https"]) == 1