"""Smart list diversity selection.""" from __future__ import annotations from datetime import UTC, datetime, timedelta import pytest from app.db.models import ProbeResult, Tracker from app.services.smart_list import SmartListFilters, build_smart_list from sqlalchemy.ext.asyncio import AsyncSession async def _seed_tracker( session: AsyncSession, *, url: str, fp: str, asn: int | None, latency: float, ) -> Tracker: now = datetime.now(UTC) t = Tracker( canonical_url=url, scheme="udp", hostname=url.split("://")[1].split(":")[0], port=80, path="/announce", current_status="up", first_seen_at=now - timedelta(days=30), last_seen_at=now, last_checked_at=now, last_latency_ms=latency, consecutive_failures=0, infrastructure_fingerprint=fp, asn=asn, supports_ipv4=True, supports_ipv6="not_tested", ) session.add(t) await session.flush() for i in range(12): session.add( ProbeResult( tracker_id=t.id, checked_at=now - timedelta(hours=i), status="up", latency_ms=latency, response_valid=True, ) ) await session.commit() return t @pytest.mark.asyncio async def test_smart_list_diversity(session: AsyncSession): await _seed_tracker(session, url="udp://a1.example:80/announce", fp="fp1", asn=100, latency=50) await _seed_tracker(session, url="udp://a2.example:80/announce", fp="fp1", asn=100, latency=40) await _seed_tracker(session, url="udp://b1.example:80/announce", fp="fp2", asn=100, latency=60) await _seed_tracker(session, url="udp://c1.example:80/announce", fp="fp3", asn=200, latency=70) entries = await build_smart_list( session, SmartListFilters(min_uptime=0.5, limit=20, diversity=True) ) urls = [e.tracker.canonical_url for e in entries] # only one of fp1 assert sum(1 for u in urls if u.startswith("udp://a")) == 1 # asn 100 at most twice asn100 = [e for e in entries if e.tracker.asn == 100] assert len(asn100) <= 2 assert "udp://c1.example:80/announce" in urls