diff --git a/tests/unit/test_neighbor_evidence_edges.py b/tests/unit/test_neighbor_evidence_edges.py index 85ef274..c8d8d98 100644 --- a/tests/unit/test_neighbor_evidence_edges.py +++ b/tests/unit/test_neighbor_evidence_edges.py @@ -9,6 +9,7 @@ from __future__ import annotations import contextlib import logging import sqlite3 +from datetime import datetime, timedelta, timezone import pytest @@ -21,8 +22,21 @@ SELF_KEY = "ff" * 32 KEY_A = "aa" * 32 KEY_B = "bb" * 32 -RECENT = "2026-08-01T00:00:00+00:00" -ANCIENT = "2020-01-01T00:00:00+00:00" + +def ago(days: float) -> str: + """A fixture timestamp `days` before now, in the format the bot stores. + + These have to be relative: the days= filters compare last_seen against + wall-clock now, so an absolute "recent" literal silently ages out of the + window and turns the filter tests red on a date nobody picked. + """ + stamp = datetime.now(timezone.utc) - timedelta(days=days) + return stamp.replace(microsecond=0).isoformat() + + +RECENT = ago(1) # inside every window these tests exercise +EARLIER = ago(250) # a lifetime first_seen, well outside a 30-day window +ANCIENT = ago(365 * 6) # outside any window the viewer offers class ViewerStub: @@ -84,7 +98,7 @@ def seeded(viewer): with viewer._with_db_connection() as conn: insert_link(conn, SELF_KEY, KEY_A, observations=4, snr_sum=30.0, snr_count=4, best_snr=9.5, last_snr=7.0, - first_seen="2026-01-01T00:00:00+00:00", last_seen=RECENT) + first_seen=EARLIER, last_seen=RECENT) insert_link(conn, SELF_KEY, KEY_B, observations=1, snr_sum=-3.0, snr_count=1, best_snr=-3.0, last_snr=-3.0, last_seen=ANCIENT) @@ -134,7 +148,7 @@ def test_edges_are_tagged_and_treated_as_first_hop(seeded): def test_edges_preserve_lifetime_counts_and_timestamps(seeded): edge = find_edge(seeded._compute_neighbor_evidence_edges(), SELF_KEY, KEY_A) assert edge["observation_count"] == 4 - assert edge["first_seen"] == "2026-01-01T00:00:00+00:00" + assert edge["first_seen"] == EARLIER assert edge["last_seen"] == RECENT @@ -192,7 +206,7 @@ def test_edge_keys_honour_the_days_window(seeded): """neighbor_links is never pruned, so stale evidence must not label edges.""" keys = seeded._neighbor_evidence_edge_keys(days=30) assert (SELF_KEY[:6], KEY_A[:6]) in keys.prefixes - # KEY_B was last heard in 2020. + # KEY_B was last heard years ago. assert (SELF_KEY[:6], KEY_B[:6]) not in keys.prefixes assert (SELF_KEY, KEY_B) not in keys.public_keys diff --git a/tests/unit/test_packet_capture_neighbors.py b/tests/unit/test_packet_capture_neighbors.py index ca13d0d..5e41b89 100644 --- a/tests/unit/test_packet_capture_neighbors.py +++ b/tests/unit/test_packet_capture_neighbors.py @@ -8,6 +8,7 @@ import contextlib import json import logging import sqlite3 +import time import types from unittest.mock import MagicMock @@ -488,28 +489,35 @@ def test_capability_false_without_a_radio(): # State persistence # --------------------------------------------------------------------------- +# _load_neighbors_timestamp rejects anything outside now-400d .. now+300s, so +# both of these have to be relative: an absolute epoch literal drifts out of +# the accepted range and fails on a date nobody picked. +STORED_EPOCH = float(round(time.time()) - 3600) +FAR_FUTURE_EPOCH = round(time.time()) + 10 * 365 * 86400 + + def test_state_round_trips_through_bot_metadata(db_manager): service = build_service(BASE_INI, db_manager=db_manager) assert service.last_neighbors_publish == 0.0 - service.last_neighbors_publish = 1774482900.0 + service.last_neighbors_publish = STORED_EPOCH service._save_neighbors_state() - assert db_manager.metadata[NEIGHBORS_STATE_KEY] == "1774482900.0" + assert db_manager.metadata[NEIGHBORS_STATE_KEY] == str(STORED_EPOCH) reloaded = build_service(BASE_INI, db_manager=db_manager) - assert reloaded.last_neighbors_publish == 1774482900.0 + assert reloaded.last_neighbors_publish == STORED_EPOCH def test_attempt_state_round_trips_through_bot_metadata(db_manager): service = build_service(BASE_INI, db_manager=db_manager) assert service.last_neighbors_attempt == 0.0 - service.last_neighbors_attempt = 1774482900.0 + service.last_neighbors_attempt = STORED_EPOCH service._save_neighbors_attempt_state() - assert db_manager.metadata[NEIGHBORS_ATTEMPT_STATE_KEY] == "1774482900.0" + assert db_manager.metadata[NEIGHBORS_ATTEMPT_STATE_KEY] == str(STORED_EPOCH) reloaded = build_service(BASE_INI, db_manager=db_manager) - assert reloaded.last_neighbors_attempt == 1774482900.0 + assert reloaded.last_neighbors_attempt == STORED_EPOCH def test_malformed_state_is_ignored(db_manager): @@ -519,7 +527,7 @@ def test_malformed_state_is_ignored(db_manager): def test_far_future_state_is_ignored(db_manager): """A clock jump forward would otherwise suppress cycles indefinitely.""" - db_manager.metadata[NEIGHBORS_STATE_KEY] = str(2**31) + db_manager.metadata[NEIGHBORS_STATE_KEY] = str(FAR_FUTURE_EPOCH) assert build_service(BASE_INI, db_manager=db_manager).last_neighbors_publish == 0.0