Skip to content

Commit 9a64353

Browse files
committed
test: pin _mark_seen FIFO eviction and add CodSpeed bench
Tighten ``test_seen_logs_is_bounded`` to assert the cap is held exactly and that the oldest 5 keys are evicted first while the newest overflow keys remain — without this, the test would have passed for ``set.pop()`` (random eviction) too, hiding any future regression away from dict-backed FIFO. Also add ``tests/benchmarks/test_mark_seen.py`` so CodSpeed tracks the three branches (hit / fill / churn) of the helper.
1 parent 4cb3ecf commit 9a64353

2 files changed

Lines changed: 48 additions & 4 deletions

File tree

tests/benchmarks/test_mark_seen.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"""Benchmark for _logger._mark_seen."""
2+
3+
from __future__ import annotations
4+
5+
from pytest_codspeed import BenchmarkFixture
6+
7+
from zeroconf._logger import _MAX_SEEN_LOGS, _mark_seen
8+
9+
10+
def test_mark_seen_hit(benchmark: BenchmarkFixture) -> None:
11+
"""Benchmark the cache-hit path (same key repeated)."""
12+
seen: dict[str, None] = {"warm": None}
13+
14+
@benchmark
15+
def _hit() -> None:
16+
for _ in range(1000):
17+
_mark_seen(seen, "warm")
18+
19+
20+
def test_mark_seen_fill(benchmark: BenchmarkFixture) -> None:
21+
"""Benchmark filling from empty up to the cap (no evictions)."""
22+
keys = [f"key-{i}" for i in range(_MAX_SEEN_LOGS)]
23+
24+
@benchmark
25+
def _fill() -> None:
26+
seen: dict[str, None] = {}
27+
for k in keys:
28+
_mark_seen(seen, k)
29+
30+
31+
def test_mark_seen_churn(benchmark: BenchmarkFixture) -> None:
32+
"""Benchmark sustained eviction (every call past the cap drops oldest)."""
33+
keys = [f"churn-{i}" for i in range(_MAX_SEEN_LOGS * 4)]
34+
35+
@benchmark
36+
def _churn() -> None:
37+
seen: dict[str, None] = {}
38+
for k in keys:
39+
_mark_seen(seen, k)

tests/test_logger.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,18 @@ def test_llog_exception_debug():
8585
assert mock_log_debug.mock_calls == [call("the exception", exc_info=False)]
8686

8787

88-
def test_seen_logs_is_bounded():
89-
"""Distinct keys must not grow ``_seen_logs`` without bound."""
88+
def test_seen_logs_is_bounded() -> None:
89+
"""``_seen_logs`` stays at the cap and evicts oldest-first (FIFO)."""
9090
_logger._seen_logs.clear()
91+
overflow = 5
9192
with patch("zeroconf._logger.log.warning"), patch("zeroconf._logger.log.debug"):
92-
for i in range(_MAX_SEEN_LOGS + 5):
93+
for i in range(_MAX_SEEN_LOGS + overflow):
9394
QuietLogger.log_warning_once(f"warning-{i}")
94-
assert len(_logger._seen_logs) <= _MAX_SEEN_LOGS
95+
assert len(_logger._seen_logs) == _MAX_SEEN_LOGS
96+
for i in range(overflow):
97+
assert f"warning-{i}" not in _logger._seen_logs
98+
for i in range(_MAX_SEEN_LOGS, _MAX_SEEN_LOGS + overflow):
99+
assert f"warning-{i}" in _logger._seen_logs
95100

96101

97102
def test_log_exception_once():

0 commit comments

Comments
 (0)