import datetime import os import sys import pytest from fastapi.testclient import TestClient sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import api_server import cidr_collector as cc import db from storage import StorageError, load_json NOW = datetime.datetime.now() @pytest.fixture def files(tmp_path, monkeypatch): monkeypatch.setattr(cc, "CONFIG_FILE", str(tmp_path / "config.json")) monkeypatch.setattr(cc, "DATA_FILE", str(tmp_path / "data.json")) monkeypatch.setattr(cc, "FQDN_DATA_FILE", str(tmp_path / "fqdn_data.json")) monkeypatch.setattr(cc, "DB_FILE", str(tmp_path / "ripe.db")) return tmp_path def stored(kind="asn"): with db.session() as conn: return sorted(db.get_values(conn, kind)) def test_ttl_merge_and_failure_safety(files, monkeypatch): (files / "config.json").write_text('{"asns": [1], "ttl_days": 90}') collector = cc.CIDRCollector() old = (NOW - datetime.timedelta(days=100)).isoformat(timespec="seconds") with db.session() as conn: conn.execute("INSERT INTO addresses VALUES ('asn', '1', '9.9.9.0/24', ?, ?)", (old, old)) # Ошибка источника: ничего не удаляется, даже просроченное monkeypatch.setattr(collector, "fetch_prefixes", lambda asn: None) collector.run_collection() assert stored() == ["9.9.9.0/24"] # Успешный ответ: просроченный удаляется, новый добавляется monkeypatch.setattr(collector, "fetch_prefixes", lambda asn: ["1.1.1.0/24"]) collector.run_collection() assert stored() == ["1.1.1.0/24"] def test_corrupted_storage_is_preserved(files): # Битый JSON (конфигурация) path = files / "data.json" path.write_text("{broken") with pytest.raises(StorageError): load_json(str(path), {}) assert not path.exists() assert len(list(files.glob("data.json.corrupt-*"))) == 1 # Битая база: убирается в сторону, ошибка отдаётся как StorageError (files / "ripe.db").write_bytes(b"this is not a sqlite database" * 100) with pytest.raises(StorageError): db.connect() assert not (files / "ripe.db").exists() assert len(list(files.glob("ripe.db.corrupt-*"))) == 1 def test_post_schedule_auth(files, monkeypatch): (files / "config.json").write_text('{"asns": [], "fqdns": []}') client = TestClient(api_server.app) body = {"type": "asn", "cron": "*/5 * * * *"} monkeypatch.delenv("RIPE_API_TOKEN", raising=False) assert client.post("/schedule", json=body).status_code == 503 monkeypatch.setenv("RIPE_API_TOKEN", "secret") assert client.post("/schedule", json=body).status_code == 401 assert client.post("/schedule", json=body, headers={"X-API-Key": "wrong"}).status_code == 401 assert client.post("/schedule", json=body, headers={"X-API-Key": "secret"}).status_code == 200 assert load_json(cc.CONFIG_FILE, {})["schedule"]["asn"] == "*/5 * * * *" assert client.get("/addresses").status_code == 200