Files
intercept/tests/test_database.py
T
James Smith 96172ca593 style: apply ruff-format to entire codebase
First-time run of ruff-format via pre-commit hook normalises quote
style, trailing commas, and whitespace across 188 Python files.
No logic changes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 14:48:11 +01:00

249 lines
9.0 KiB
Python

"""Tests for database utilities."""
import tempfile
from pathlib import Path
from unittest.mock import patch
import pytest
# Need to patch DB_PATH before importing database module
@pytest.fixture(autouse=True)
def temp_db():
"""Use a temporary database for each test."""
with tempfile.TemporaryDirectory() as tmpdir:
test_db_path = Path(tmpdir) / "test_intercept.db"
test_db_dir = Path(tmpdir)
with patch("utils.database.DB_PATH", test_db_path), patch("utils.database.DB_DIR", test_db_dir):
# Import after patching
from utils.database import close_db, init_db
init_db()
yield test_db_path
close_db()
class TestSettingsCRUD:
"""Tests for settings CRUD operations."""
def test_set_and_get_string(self, temp_db):
"""Test setting and getting string values."""
from utils.database import get_setting, set_setting
set_setting("test_key", "test_value")
assert get_setting("test_key") == "test_value"
def test_set_and_get_int(self, temp_db):
"""Test setting and getting integer values."""
from utils.database import get_setting, set_setting
set_setting("int_key", 42)
result = get_setting("int_key")
assert result == 42
assert isinstance(result, int)
def test_set_and_get_float(self, temp_db):
"""Test setting and getting float values."""
from utils.database import get_setting, set_setting
set_setting("float_key", 3.14)
result = get_setting("float_key")
assert result == 3.14
assert isinstance(result, float)
def test_set_and_get_bool(self, temp_db):
"""Test setting and getting boolean values."""
from utils.database import get_setting, set_setting
set_setting("bool_true", True)
set_setting("bool_false", False)
assert get_setting("bool_true") is True
assert get_setting("bool_false") is False
def test_set_and_get_dict(self, temp_db):
"""Test setting and getting dictionary values."""
from utils.database import get_setting, set_setting
test_dict = {"name": "test", "value": 123, "nested": {"a": 1}}
set_setting("dict_key", test_dict)
result = get_setting("dict_key")
assert result == test_dict
assert result["nested"]["a"] == 1
def test_set_and_get_list(self, temp_db):
"""Test setting and getting list values."""
from utils.database import get_setting, set_setting
test_list = [1, 2, 3, "four", {"five": 5}]
set_setting("list_key", test_list)
result = get_setting("list_key")
assert result == test_list
def test_get_nonexistent_key(self, temp_db):
"""Test getting a key that doesn't exist."""
from utils.database import get_setting
assert get_setting("nonexistent") is None
assert get_setting("nonexistent", "default") == "default"
def test_update_existing_setting(self, temp_db):
"""Test updating an existing setting."""
from utils.database import get_setting, set_setting
set_setting("update_key", "original")
assert get_setting("update_key") == "original"
set_setting("update_key", "updated")
assert get_setting("update_key") == "updated"
def test_delete_setting(self, temp_db):
"""Test deleting a setting."""
from utils.database import delete_setting, get_setting, set_setting
set_setting("delete_key", "value")
assert get_setting("delete_key") == "value"
result = delete_setting("delete_key")
assert result is True
assert get_setting("delete_key") is None
def test_delete_nonexistent_setting(self, temp_db):
"""Test deleting a setting that doesn't exist."""
from utils.database import delete_setting
result = delete_setting("nonexistent_key")
assert result is False
def test_get_all_settings(self, temp_db):
"""Test getting all settings."""
from utils.database import get_all_settings, set_setting
set_setting("key1", "value1")
set_setting("key2", 42)
set_setting("key3", True)
all_settings = get_all_settings()
assert "key1" in all_settings
assert all_settings["key1"] == "value1"
assert all_settings["key2"] == 42
assert all_settings["key3"] is True
class TestSignalHistory:
"""Tests for signal history operations."""
def test_add_and_get_signal_reading(self, temp_db):
"""Test adding and retrieving signal readings."""
from utils.database import add_signal_reading, get_signal_history
add_signal_reading("wifi", "AA:BB:CC:DD:EE:FF", -65)
add_signal_reading("wifi", "AA:BB:CC:DD:EE:FF", -62)
add_signal_reading("wifi", "AA:BB:CC:DD:EE:FF", -70)
history = get_signal_history("wifi", "AA:BB:CC:DD:EE:FF")
assert len(history) == 3
# Results should be in chronological order
assert history[0]["signal"] == -65
assert history[1]["signal"] == -62
assert history[2]["signal"] == -70
def test_signal_history_with_metadata(self, temp_db):
"""Test signal readings with metadata."""
from utils.database import add_signal_reading, get_signal_history
metadata = {"channel": 6, "ssid": "TestNetwork"}
add_signal_reading("wifi", "AA:BB:CC:DD:EE:FF", -65, metadata)
history = get_signal_history("wifi", "AA:BB:CC:DD:EE:FF")
assert len(history) == 1
assert history[0]["metadata"] == metadata
def test_signal_history_limit(self, temp_db):
"""Test signal history respects limit parameter."""
from utils.database import add_signal_reading, get_signal_history
for i in range(10):
add_signal_reading("wifi", "AA:BB:CC:DD:EE:FF", -60 - i)
history = get_signal_history("wifi", "AA:BB:CC:DD:EE:FF", limit=5)
assert len(history) == 5
def test_signal_history_different_devices(self, temp_db):
"""Test signal history isolates different devices."""
from utils.database import add_signal_reading, get_signal_history
add_signal_reading("wifi", "AA:AA:AA:AA:AA:AA", -65)
add_signal_reading("wifi", "BB:BB:BB:BB:BB:BB", -70)
history_a = get_signal_history("wifi", "AA:AA:AA:AA:AA:AA")
history_b = get_signal_history("wifi", "BB:BB:BB:BB:BB:BB")
assert len(history_a) == 1
assert len(history_b) == 1
assert history_a[0]["signal"] == -65
assert history_b[0]["signal"] == -70
def test_cleanup_old_signal_history(self, temp_db):
"""Test cleanup of old signal history."""
from utils.database import add_signal_reading, cleanup_old_signal_history
add_signal_reading("wifi", "AA:BB:CC:DD:EE:FF", -65)
# Cleanup with 0 hours should remove everything
deleted = cleanup_old_signal_history(max_age_hours=0)
# Note: This may or may not delete depending on timing
assert isinstance(deleted, int)
class TestDeviceCorrelations:
"""Tests for device correlation operations."""
def test_add_and_get_correlation(self, temp_db):
"""Test adding and retrieving correlations."""
from utils.database import add_correlation, get_correlations
add_correlation(
wifi_mac="AA:AA:AA:AA:AA:AA", bt_mac="BB:BB:BB:BB:BB:BB", confidence=0.85, metadata={"reason": "timing"}
)
correlations = get_correlations(min_confidence=0.5)
assert len(correlations) >= 1
found = next((c for c in correlations if c["wifi_mac"] == "AA:AA:AA:AA:AA:AA"), None)
assert found is not None
assert found["bt_mac"] == "BB:BB:BB:BB:BB:BB"
assert found["confidence"] == 0.85
def test_correlation_confidence_filter(self, temp_db):
"""Test correlation filtering by confidence."""
from utils.database import add_correlation, get_correlations
add_correlation("AA:AA:AA:AA:AA:AA", "BB:BB:BB:BB:BB:BB", 0.9)
add_correlation("CC:CC:CC:CC:CC:CC", "DD:DD:DD:DD:DD:DD", 0.4)
high_confidence = get_correlations(min_confidence=0.7)
all_confidence = get_correlations(min_confidence=0.3)
assert len(high_confidence) == 1
assert len(all_confidence) == 2
def test_correlation_upsert(self, temp_db):
"""Test that correlations are updated on conflict."""
from utils.database import add_correlation, get_correlations
add_correlation("AA:AA:AA:AA:AA:AA", "BB:BB:BB:BB:BB:BB", 0.5)
add_correlation("AA:AA:AA:AA:AA:AA", "BB:BB:BB:BB:BB:BB", 0.9)
correlations = get_correlations(min_confidence=0.0)
matching = [c for c in correlations if c["wifi_mac"] == "AA:AA:AA:AA:AA:AA"]
assert len(matching) == 1
assert matching[0]["confidence"] == 0.9