import os import pytest from django.conf import settings from tracker.services.geo import GeoResolver, parse_region XDB_EXISTS = os.path.exists(settings.IP2REGION_XDB) def test_private_ip_returns_local(): r = GeoResolver() assert r.resolve("192.168.1.5") is None # 内网不解析(后台显示"本地") assert r.resolve("127.0.0.1") is None def test_public_ip_parsed_or_none(monkeypatch): r = GeoResolver() # xdb 未下载/解析失败时优雅降级返回 None,不抛异常 out = r.resolve("8.8.8.8") assert out is None or set(out) == {"country", "province", "city"} def test_parse_region_two_layouts(): # 旧版 2.0 结构:"国家|区域|省|市|ISP" assert parse_region("中国|0|江苏省|南京市|电信", new_layout=False) == { "country": "中国", "province": "江苏省", "city": "南京市"} # 新版 3.0 结构(v4/v6 库):"国家|省/区域|城市|ISP|国家代码" assert parse_region("中国|江苏省|南京市|0|CN", new_layout=True) == { "country": "中国", "province": "江苏省", "city": "南京市"} # ISP 段不得串进 city assert parse_region("United States|California|0|Google LLC|US", new_layout=True) == { "country": "United States", "province": "California", "city": "0"} assert parse_region("", new_layout=True) is None assert parse_region("中国", new_layout=True) is None # 不足 4 段 assert parse_region(None, new_layout=False) is None class _FakeSearcher: def __init__(self, raw): self._raw = raw def search(self, ip): return self._raw def test_resolve_uses_layout_dispatch(): r = GeoResolver() r._searcher = _FakeSearcher("中国|北京市|北京市|百度|CN") r._new_layout = True assert r.resolve("1.2.3.4") == { "country": "中国", "province": "北京市", "city": "北京市"} r2 = GeoResolver() r2._searcher = _FakeSearcher("中国|华北|北京市|北京市|百度") r2._new_layout = False assert r2.resolve("1.2.3.4") == { "country": "中国", "province": "北京市", "city": "北京市"} @pytest.mark.skipif(not XDB_EXISTS, reason="ip2region.xdb 未下载,跳过真实解析探针") def test_real_probe_public_ip(): r = GeoResolver() assert r._searcher is not None, "xdb 存在时必须成功加载" raw = r._searcher.search("8.8.8.8") assert len(raw.split("|")) == 5, f"应为五段格式,实际: {raw!r}" out = r.resolve("8.8.8.8") assert set(out) == {"country", "province", "city"} assert out["country"] in ("美国", "United States") assert out["city"] != "Google LLC", "ISP 不得串进 city(布局映射错误)" cn = r.resolve("114.114.114.114") assert cn["country"] == "中国" assert cn["province"] not in ("", "0"), "国内公网 IP 应解析出省份"