Files
intercept/tests/test_signalid_match.py
T
James Smith 115dffd18e feat: add signal_db loader and match_signals scoring function
Implements lazy-cached load_signals() and pure match_signals() with
frequency/bandwidth/modulation/region scoring for the signal ID feature.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 08:10:47 +01:00

140 lines
6.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Unit tests for the signal database loader and match function."""
from __future__ import annotations
import pytest
class TestLoadSignals:
def test_returns_list(self):
from utils.signal_db import load_signals
signals = load_signals()
assert isinstance(signals, list)
assert len(signals) > 0
def test_cached_on_second_call(self):
from utils.signal_db import load_signals
first = load_signals()
second = load_signals()
assert first is second # same object — cached
class TestMatchSignals:
def test_fm_broadcast_matched_at_center(self):
from utils.signal_db import match_signals
results = match_signals(frequency_mhz=98.5)
names = [r["name"] for r in results]
assert "FM Broadcast Radio" in names
def test_frequency_at_exact_range_boundary_included(self):
from utils.signal_db import match_signals
# 87.5 MHz is the lower bound of FM broadcast
results = match_signals(frequency_mhz=87.5)
names = [r["name"] for r in results]
assert "FM Broadcast Radio" in names
def test_frequency_just_outside_range_excluded(self):
from utils.signal_db import match_signals
# 87.499 MHz is just below FM broadcast lower bound
results = match_signals(frequency_mhz=87.499)
names = [r["name"] for r in results]
assert "FM Broadcast Radio" not in names
def test_no_matches_returns_empty_list(self):
from utils.signal_db import match_signals
# 5000 MHz has no signals in our database
results = match_signals(frequency_mhz=5000.0)
assert results == []
def test_results_have_score_field(self):
from utils.signal_db import match_signals
results = match_signals(frequency_mhz=98.5)
assert len(results) > 0
for r in results:
assert "score" in r
assert isinstance(r["score"], int)
assert 0 <= r["score"] <= 100
def test_results_have_match_reasons(self):
from utils.signal_db import match_signals
results = match_signals(frequency_mhz=98.5)
assert len(results) > 0
for r in results:
assert "match_reasons" in r
assert isinstance(r["match_reasons"], list)
def test_results_sorted_by_score_descending(self):
from utils.signal_db import match_signals
results = match_signals(frequency_mhz=98.5)
scores = [r["score"] for r in results]
assert scores == sorted(scores, reverse=True)
def test_limit_respected(self):
from utils.signal_db import match_signals
results = match_signals(frequency_mhz=98.5, limit=2)
assert len(results) <= 2
def test_limit_clamped_to_minimum_1(self):
from utils.signal_db import match_signals
results = match_signals(frequency_mhz=98.5, limit=0)
assert len(results) >= 1
def test_bandwidth_within_range_scores_higher(self):
from utils.signal_db import match_signals
# FM broadcast bandwidth_range is 150k250k Hz; 200k is within
with_bw = match_signals(frequency_mhz=98.5, bandwidth_hz=200_000)
without_bw = match_signals(frequency_mhz=98.5)
fm_with = next(r for r in with_bw if r["name"] == "FM Broadcast Radio")
fm_without = next(r for r in without_bw if r["name"] == "FM Broadcast Radio")
assert fm_with["score"] >= fm_without["score"]
def test_bandwidth_outside_2x_scores_zero_for_bw_criterion(self):
from utils.signal_db import match_signals
# FM broadcast max_bw is 250k Hz; 600k is > 2× that
results = match_signals(frequency_mhz=98.5, bandwidth_hz=600_000)
fm = next((r for r in results if r["name"] == "FM Broadcast Radio"), None)
# FM may still appear due to frequency score, but BW reason should not be "within typical"
if fm:
assert "bandwidth: within typical" not in fm["match_reasons"]
def test_modulation_exact_match_scores_higher(self):
from utils.signal_db import match_signals
with_mod = match_signals(frequency_mhz=98.5, modulation="WFM")
without_mod = match_signals(frequency_mhz=98.5)
fm_with = next(r for r in with_mod if r["name"] == "FM Broadcast Radio")
fm_without = next(r for r in without_mod if r["name"] == "FM Broadcast Radio")
assert fm_with["score"] >= fm_without["score"]
def test_modulation_mismatch_no_mod_reason(self):
from utils.signal_db import match_signals
results = match_signals(frequency_mhz=98.5, modulation="LSB")
fm = next((r for r in results if r["name"] == "FM Broadcast Radio"), None)
if fm:
assert "modulation: exact match" not in fm["match_reasons"]
def test_multi_range_signal_matched_by_any_range(self):
from utils.signal_db import match_signals
# POCSAG has ranges in 138-175 MHz and 450-470 MHz
# 162 MHz is in the first range (maritime VHF area, but also POCSAG territory)
results_vhf = match_signals(frequency_mhz=155.0)
results_uhf = match_signals(frequency_mhz=455.0)
vhf_names = [r["name"] for r in results_vhf]
uhf_names = [r["name"] for r in results_uhf]
assert "POCSAG Pager" in vhf_names
assert "POCSAG Pager" in uhf_names
def test_region_mismatch_does_not_exclude_signal(self):
from utils.signal_db import match_signals
# PMR446 is EU/UK only; should still appear with US region but may score lower
results = match_signals(frequency_mhz=446.09375, region="US")
names = [r["name"] for r in results]
assert "PMR446 (Licence-Free UHF)" in names
def test_original_signal_dict_not_mutated(self):
from utils.signal_db import load_signals, match_signals
original = load_signals()
first_id_before = original[0]["id"]
match_signals(frequency_mhz=98.5, modulation="WFM")
assert original[0]["id"] == first_id_before # not mutated
assert "score" not in original[0] # score not added in-place