mirror of
https://github.com/feder-cr/invisible_playwright.git
synced 2026-06-07 08:35:12 +02:00
Refine timezone="auto" so it ALWAYS resolves (drop the "host" sentinel): - ""/"auto" resolve from the proxy egress when a proxy is set, else from the host own public IP (direct lookup); an explicit zone is the only opt-out. - on failure: with a proxy raise; without a proxy fall back to the host TZ. GeoIP DB now auto-updates against daijro/geoip-all-in-one weekly rebuild: cache the latest, re-check after GEOIP_REFRESH_DAYS (7), prune old tags, reuse a stale cache offline; GEOIP_MMDB_VERSION is only the cold fallback. tests: test_geo.py (37) + test_geoip_update.py; full unit suite 429 green plus 8 live combinations (proxy / no-proxy / explicit / failing / freshness).
131 lines
5.1 KiB
Python
131 lines
5.1 KiB
Python
"""Unit tests for the intelligent geoip mmdb auto-update in `download.py`.
|
|
|
|
daijro/geoip-all-in-one rebuilds weekly; `ensure_geoip_mmdb` keeps the cache
|
|
fresh without a download (or API call) on every launch. These tests mock the
|
|
cache root, the latest-tag API, and the per-tag download so nothing touches the
|
|
network.
|
|
"""
|
|
import os
|
|
import time
|
|
|
|
import pytest
|
|
|
|
import invisible_playwright.download as dl
|
|
|
|
|
|
@pytest.fixture
|
|
def cache(tmp_path, monkeypatch):
|
|
"""Point the cache at tmp_path and clear the env override."""
|
|
monkeypatch.setattr(dl, "cache_root", lambda: tmp_path)
|
|
monkeypatch.delenv("STEALTHFOX_GEOIP_MMDB", raising=False)
|
|
return tmp_path
|
|
|
|
|
|
def _make_cached(root, tag, name=dl.GEOIP_MMDB_NAME):
|
|
d = root / "geoip" / tag
|
|
d.mkdir(parents=True, exist_ok=True)
|
|
f = d / name
|
|
f.write_bytes(b"FAKE-MMDB")
|
|
return f
|
|
|
|
|
|
def _set_marker_age(root, days):
|
|
m = root / "geoip" / ".last_check"
|
|
m.parent.mkdir(parents=True, exist_ok=True)
|
|
m.touch()
|
|
old = time.time() - days * 86400
|
|
os.utime(m, (old, old))
|
|
|
|
|
|
# ──────────────────────────────────────────────────────────────────────
|
|
# env override
|
|
# ──────────────────────────────────────────────────────────────────────
|
|
@pytest.mark.unit
|
|
def test_env_override_returns_file(tmp_path, monkeypatch):
|
|
f = tmp_path / "mine.mmdb"
|
|
f.write_bytes(b"X")
|
|
monkeypatch.setenv("STEALTHFOX_GEOIP_MMDB", str(f))
|
|
assert dl.ensure_geoip_mmdb() == f
|
|
|
|
|
|
@pytest.mark.unit
|
|
def test_env_override_missing_raises(tmp_path, monkeypatch):
|
|
monkeypatch.setenv("STEALTHFOX_GEOIP_MMDB", str(tmp_path / "nope.mmdb"))
|
|
with pytest.raises(RuntimeError):
|
|
dl.ensure_geoip_mmdb()
|
|
|
|
|
|
# ──────────────────────────────────────────────────────────────────────
|
|
# freshness window
|
|
# ──────────────────────────────────────────────────────────────────────
|
|
@pytest.mark.unit
|
|
def test_fresh_cache_no_network(cache, monkeypatch):
|
|
f = _make_cached(cache, "2026.06.03")
|
|
_set_marker_age(cache, 0) # just checked
|
|
|
|
def boom():
|
|
raise AssertionError("latest-tag API must NOT be called within the window")
|
|
|
|
monkeypatch.setattr(dl, "_latest_geoip_tag", boom)
|
|
assert dl.ensure_geoip_mmdb(max_age_days=7) == f
|
|
|
|
|
|
@pytest.mark.unit
|
|
def test_stale_same_tag_no_download(cache, monkeypatch):
|
|
f = _make_cached(cache, "2026.06.03")
|
|
_set_marker_age(cache, 30) # stale → will re-check
|
|
monkeypatch.setattr(dl, "_latest_geoip_tag", lambda: "2026.06.03")
|
|
# real _download_geoip_tag runs but target exists, so no actual download:
|
|
monkeypatch.setattr(dl, "_download_file", lambda *a, **k: (_ for _ in ()).throw(
|
|
AssertionError("must not download when tag already cached")))
|
|
assert dl.ensure_geoip_mmdb(max_age_days=7) == f
|
|
|
|
|
|
@pytest.mark.unit
|
|
def test_stale_new_tag_downloads_and_prunes(cache, monkeypatch):
|
|
old = _make_cached(cache, "2026.06.03")
|
|
_set_marker_age(cache, 30)
|
|
monkeypatch.setattr(dl, "_latest_geoip_tag", lambda: "2026.06.10")
|
|
|
|
def fake_download(tag):
|
|
return _make_cached(cache, tag) # simulate fetch+extract of the new tag
|
|
|
|
monkeypatch.setattr(dl, "_download_geoip_tag", fake_download)
|
|
got = dl.ensure_geoip_mmdb(max_age_days=7)
|
|
assert got.parent.name == "2026.06.10"
|
|
assert not old.parent.exists() # old tag pruned
|
|
assert got.exists()
|
|
|
|
|
|
# ──────────────────────────────────────────────────────────────────────
|
|
# offline resilience
|
|
# ──────────────────────────────────────────────────────────────────────
|
|
@pytest.mark.unit
|
|
def test_api_down_with_cache_uses_cache(cache, monkeypatch):
|
|
f = _make_cached(cache, "2026.06.03")
|
|
_set_marker_age(cache, 30)
|
|
|
|
def boom():
|
|
raise OSError("offline")
|
|
|
|
monkeypatch.setattr(dl, "_latest_geoip_tag", boom)
|
|
assert dl.ensure_geoip_mmdb(max_age_days=7) == f # stale cache reused, no raise
|
|
|
|
|
|
@pytest.mark.unit
|
|
def test_cold_cache_api_down_falls_back_to_pinned(cache, monkeypatch):
|
|
# no cache at all + API unreachable → pinned GEOIP_MMDB_VERSION fallback.
|
|
def boom():
|
|
raise OSError("offline")
|
|
|
|
monkeypatch.setattr(dl, "_latest_geoip_tag", boom)
|
|
captured = {}
|
|
|
|
def fake_download(tag):
|
|
captured["tag"] = tag
|
|
return _make_cached(cache, tag)
|
|
|
|
monkeypatch.setattr(dl, "_download_geoip_tag", fake_download)
|
|
got = dl.ensure_geoip_mmdb(max_age_days=7)
|
|
assert captured["tag"] == dl.GEOIP_MMDB_VERSION
|
|
assert got.exists()
|