fixed tests
This commit is contained in:
@@ -209,9 +209,7 @@ class TestLookupCaching:
|
||||
|
||||
async def test_negative_result_stored_in_neg_cache(self, geo_cache: GeoCache) -> None:
|
||||
"""A failed lookup is stored in the negative cache, so the second call is blocked."""
|
||||
session = _make_session(
|
||||
{"status": "fail", "message": "reserved range"}
|
||||
)
|
||||
session = _make_session({"status": "fail", "message": "reserved range"})
|
||||
|
||||
await geo_cache.lookup("192.168.1.1", session)
|
||||
await geo_cache.lookup("192.168.1.1", session)
|
||||
@@ -473,7 +471,7 @@ def _make_async_db() -> MagicMock:
|
||||
return MagicMock(__aenter__=AsyncMock(return_value=None), __aexit__=AsyncMock(return_value=None))
|
||||
return mock_ctx
|
||||
|
||||
db.execute = MagicMock(side_effect=fake_execute)
|
||||
db.execute = AsyncMock(side_effect=fake_execute)
|
||||
db.executemany = AsyncMock()
|
||||
db.commit = AsyncMock()
|
||||
db.rollback = AsyncMock()
|
||||
@@ -500,10 +498,7 @@ class TestLookupBatchSingleCommit:
|
||||
async def test_commit_called_even_on_failed_lookups(self, geo_cache: GeoCache) -> None:
|
||||
"""A batch with all-failed lookups still triggers one commit."""
|
||||
ips = ["10.0.0.1", "10.0.0.2"]
|
||||
batch_response = [
|
||||
{"query": ip, "status": "fail", "message": "private range"}
|
||||
for ip in ips
|
||||
]
|
||||
batch_response = [{"query": ip, "status": "fail", "message": "private range"} for ip in ips]
|
||||
session = _make_batch_session(batch_response)
|
||||
db = _make_async_db()
|
||||
|
||||
@@ -533,9 +528,7 @@ class TestLookupBatchSingleCommit:
|
||||
|
||||
async def test_no_commit_for_all_cached_ips(self, geo_cache: GeoCache) -> None:
|
||||
"""When all IPs are already cached, no HTTP call and no commit occur."""
|
||||
geo_cache._cache["5.5.5.5"] = GeoInfo(
|
||||
country_code="FR", country_name="France", asn="AS1", org="ISP"
|
||||
)
|
||||
geo_cache._cache["5.5.5.5"] = GeoInfo(country_code="FR", country_name="France", asn="AS1", org="ISP")
|
||||
db = _make_async_db()
|
||||
session = _make_batch_session([])
|
||||
|
||||
@@ -670,10 +663,7 @@ class TestLookupBatchThrottling:
|
||||
ips = [f"10.0.{i // 256}.{i % 256}" for i in range(batch_size + 1)]
|
||||
|
||||
def _make_result(chunk: list[str], _session: object) -> dict[str, GeoInfo]:
|
||||
return {
|
||||
ip: GeoInfo(country_code="DE", country_name="Germany", asn=None, org=None)
|
||||
for ip in chunk
|
||||
}
|
||||
return {ip: GeoInfo(country_code="DE", country_name="Germany", asn=None, org=None) for ip in chunk}
|
||||
|
||||
with (
|
||||
patch.object(
|
||||
@@ -778,7 +768,7 @@ class TestErrorLogging:
|
||||
async def test_empty_message_exception_logs_exc_type(self, geo_cache: GeoCache) -> None:
|
||||
"""When HTTP exception str() is empty, exc_type and repr are still logged."""
|
||||
|
||||
class _EmptyMessageError(Exception):
|
||||
class _EmptyMessageError(OSError):
|
||||
"""Exception whose str() representation is empty."""
|
||||
|
||||
def __str__(self) -> str:
|
||||
@@ -792,9 +782,7 @@ class TestErrorLogging:
|
||||
|
||||
from tests.logging_capture import capture_logs
|
||||
|
||||
with capture_logs() as captured, patch.object(
|
||||
geo_cache, "_geoip_reader", None
|
||||
):
|
||||
with capture_logs() as captured, patch.object(geo_cache, "_geoip_reader", None):
|
||||
# Ensure MMDB is not available so HTTP is tried.
|
||||
result = await geo_cache.lookup("197.221.98.153", session)
|
||||
|
||||
@@ -819,9 +807,7 @@ class TestErrorLogging:
|
||||
|
||||
from tests.logging_capture import capture_logs
|
||||
|
||||
with capture_logs() as captured, patch.object(
|
||||
geo_cache, "_geoip_reader", None
|
||||
):
|
||||
with capture_logs() as captured, patch.object(geo_cache, "_geoip_reader", None):
|
||||
# Ensure MMDB is not available so HTTP is tried.
|
||||
await geo_cache.lookup("10.0.0.1", session)
|
||||
|
||||
@@ -834,7 +820,7 @@ class TestErrorLogging:
|
||||
async def test_batch_empty_message_exception_logs_exc_type(self, geo_cache: GeoCache) -> None:
|
||||
"""Batch API call: empty-message exceptions include exc_type in the log."""
|
||||
|
||||
class _EmptyMessageError(Exception):
|
||||
class _EmptyMessageError(OSError):
|
||||
def __str__(self) -> str:
|
||||
return ""
|
||||
|
||||
@@ -908,9 +894,7 @@ class TestLookupCachedOnly:
|
||||
|
||||
def test_mixed_ips(self, geo_cache: GeoCache) -> None:
|
||||
"""A mix of cached, neg-cached, and unknown IPs is split correctly."""
|
||||
geo_cache._cache["1.2.3.4"] = GeoInfo(
|
||||
country_code="DE", country_name="Germany", asn=None, org=None
|
||||
)
|
||||
geo_cache._cache["1.2.3.4"] = GeoInfo(country_code="DE", country_name="Germany", asn=None, org=None)
|
||||
import time
|
||||
|
||||
geo_cache._neg_cache["5.5.5.5"] = time.monotonic()
|
||||
@@ -922,13 +906,9 @@ class TestLookupCachedOnly:
|
||||
|
||||
def test_deduplication(self, geo_cache: GeoCache) -> None:
|
||||
"""Duplicate IPs in the input appear at most once in the output."""
|
||||
geo_cache._cache["1.2.3.4"] = GeoInfo(
|
||||
country_code="US", country_name="United States", asn=None, org=None
|
||||
)
|
||||
geo_cache._cache["1.2.3.4"] = GeoInfo(country_code="US", country_name="United States", asn=None, org=None)
|
||||
|
||||
geo_map, uncached = geo_cache.lookup_cached_only(
|
||||
["9.9.9.9", "9.9.9.9", "1.2.3.4", "1.2.3.4"]
|
||||
)
|
||||
geo_map, uncached = geo_cache.lookup_cached_only(["9.9.9.9", "9.9.9.9", "1.2.3.4", "1.2.3.4"])
|
||||
|
||||
assert len([ip for ip in geo_map if ip == "1.2.3.4"]) == 1
|
||||
assert uncached.count("9.9.9.9") == 1
|
||||
@@ -942,18 +922,22 @@ class TestReResolveAll:
|
||||
db = MagicMock()
|
||||
session = MagicMock()
|
||||
|
||||
with patch(
|
||||
"app.repositories.geo_cache_repo.get_unresolved_ips",
|
||||
AsyncMock(return_value=[]),
|
||||
), patch.object(
|
||||
geo_cache,
|
||||
"lookup_batch",
|
||||
AsyncMock(),
|
||||
) as mock_lookup, patch.object(
|
||||
geo_cache,
|
||||
"clear_neg_cache",
|
||||
AsyncMock(),
|
||||
) as mock_clear:
|
||||
with (
|
||||
patch(
|
||||
"app.repositories.geo_cache_repo.get_unresolved_ips",
|
||||
AsyncMock(return_value=[]),
|
||||
),
|
||||
patch.object(
|
||||
geo_cache,
|
||||
"lookup_batch",
|
||||
AsyncMock(),
|
||||
) as mock_lookup,
|
||||
patch.object(
|
||||
geo_cache,
|
||||
"clear_neg_cache",
|
||||
AsyncMock(),
|
||||
) as mock_clear,
|
||||
):
|
||||
result = await geo_cache.re_resolve_all(db, session)
|
||||
|
||||
assert result == {"resolved": 0, "total": 0}
|
||||
@@ -970,18 +954,22 @@ class TestReResolveAll:
|
||||
"2.2.2.2": GeoInfo(country_code=None, country_name=None, asn=None, org=None),
|
||||
}
|
||||
|
||||
with patch(
|
||||
"app.repositories.geo_cache_repo.get_unresolved_ips",
|
||||
AsyncMock(return_value=ips),
|
||||
), patch.object(
|
||||
geo_cache,
|
||||
"lookup_batch",
|
||||
AsyncMock(return_value=geo_map),
|
||||
) as mock_lookup, patch.object(
|
||||
geo_cache,
|
||||
"clear_neg_cache",
|
||||
AsyncMock(),
|
||||
) as mock_clear:
|
||||
with (
|
||||
patch(
|
||||
"app.repositories.geo_cache_repo.get_unresolved_ips",
|
||||
AsyncMock(return_value=ips),
|
||||
),
|
||||
patch.object(
|
||||
geo_cache,
|
||||
"lookup_batch",
|
||||
AsyncMock(return_value=geo_map),
|
||||
) as mock_lookup,
|
||||
patch.object(
|
||||
geo_cache,
|
||||
"clear_neg_cache",
|
||||
AsyncMock(),
|
||||
) as mock_clear,
|
||||
):
|
||||
result = await geo_cache.re_resolve_all(db, session)
|
||||
|
||||
assert result == {"resolved": 1, "total": 2}
|
||||
@@ -1018,23 +1006,21 @@ class TestLookupBatchBulkWrites:
|
||||
|
||||
# One executemany for the positive rows.
|
||||
assert db.executemany.await_count >= 1
|
||||
# High-level: execute() must NOT be called for the batch writes.
|
||||
db.execute.assert_not_awaited()
|
||||
# BEGIN IMMEDIATE is called for transaction wrapper.
|
||||
assert db.execute.await_count == 1
|
||||
|
||||
async def test_executemany_called_for_failed_ips(self, geo_cache: GeoCache) -> None:
|
||||
"""When IPs fail resolution, a single executemany write covers neg entries."""
|
||||
ips = ["10.0.0.1", "10.0.0.2"]
|
||||
batch_response = [
|
||||
{"query": ip, "status": "fail", "message": "private range"}
|
||||
for ip in ips
|
||||
]
|
||||
batch_response = [{"query": ip, "status": "fail", "message": "private range"} for ip in ips]
|
||||
session = _make_batch_session(batch_response)
|
||||
db = _make_async_db()
|
||||
|
||||
await geo_cache.lookup_batch(ips, session, db=db)
|
||||
|
||||
assert db.executemany.await_count >= 1
|
||||
db.execute.assert_not_awaited()
|
||||
# BEGIN IMMEDIATE is called for transaction wrapper.
|
||||
assert db.execute.await_count == 1
|
||||
|
||||
async def test_mixed_results_two_executemany_calls(self, geo_cache: GeoCache) -> None:
|
||||
"""A mix of successful and failed IPs produces two executemany calls."""
|
||||
@@ -1057,7 +1043,8 @@ class TestLookupBatchBulkWrites:
|
||||
|
||||
# One executemany for positives, one for negatives.
|
||||
assert db.executemany.await_count == 2
|
||||
db.execute.assert_not_awaited()
|
||||
# BEGIN IMMEDIATE is called for transaction wrapper.
|
||||
assert db.execute.await_count == 1
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -1071,9 +1058,7 @@ class TestCacheMetrics:
|
||||
async def test_cache_hit_increments_hits(self) -> None:
|
||||
"""lookup() with a cached IP increments _hits."""
|
||||
geo_cache = GeoCache(allow_http_fallback=True)
|
||||
geo_cache._cache["1.1.1.1"] = GeoInfo(
|
||||
country_code="AU", country_name="Australia", asn=None, org=None
|
||||
)
|
||||
geo_cache._cache["1.1.1.1"] = GeoInfo(country_code="AU", country_name="Australia", asn=None, org=None)
|
||||
|
||||
await geo_cache.lookup("1.1.1.1", MagicMock())
|
||||
|
||||
@@ -1269,4 +1254,3 @@ class TestLargeBanList:
|
||||
|
||||
assert len(result) == 1
|
||||
assert "1.1.1.1" in result
|
||||
|
||||
|
||||
Reference in New Issue
Block a user