Files
intercept/tests/test_bluetooth.py
Smittix e00fbfddc1 v2.26.0: fix SSE fanout crash and branded logo FOUC
- Fix SSE fanout thread AttributeError when source queue is None during
  interpreter shutdown by snapshotting to local variable with null guard
- Fix branded "i" logo rendering oversized on first page load (FOUC) by
  adding inline width/height to SVG elements across 10 templates
- Bump version to 2.26.0 in config.py, pyproject.toml, and CHANGELOG.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 11:51:27 +00:00

130 lines
4.2 KiB
Python

from unittest.mock import MagicMock, patch
import pytest
from flask import Flask
from routes.bluetooth import bluetooth_bp, classify_bt_device, detect_tracker
@pytest.fixture(autouse=True)
def mock_app_module(mocker):
mock_app = mocker.patch("routes.bluetooth.app_module")
mock_app.bt_devices = {}
mock_app.bt_beacons = {}
mock_app.bt_services = {}
mock_app.bt_queue = MagicMock()
mock_app.bt_lock = MagicMock()
mock_app.bt_process = None
mock_app.bt_interface = "hci0"
return mock_app
@pytest.fixture
def app():
app = Flask(__name__)
app.register_blueprint(bluetooth_bp)
return app
@pytest.fixture
def client(app):
return app.test_client()
def test_classify_bt_device_by_name():
"""Test classification based on common naming patterns."""
assert classify_bt_device("Sony WH-1000XM4", None, None) == "audio"
assert classify_bt_device("iPhone 15", None, None) == "phone"
assert classify_bt_device("Garmin Fenix", None, None) == "wearable"
assert classify_bt_device("Microsoft Mouse", None, None) == "input"
assert classify_bt_device("AirTag", None, None) == "tracker"
assert classify_bt_device("Generic Device", None, None) == "other"
def test_classify_bt_device_by_class():
"""Test classification based on Bluetooth Class of Device (CoD)."""
assert classify_bt_device(None, 0x0100, None) == "computer"
assert classify_bt_device(None, 0x0200, None) == "phone"
assert classify_bt_device(None, 0x0400, None) == "audio"
def test_detect_tracker_by_mac():
"""Test tracker detection using MAC OUI prefixes."""
# Assuming 'FF:FF:FF' is a mock prefix in patterns for testing
with patch("routes.bluetooth.TILE_PREFIXES", ["FF:FF"]):
result = detect_tracker("FF:FF:00:11:22:33", "Unknown")
assert result["type"] == "tile"
def test_detect_tracker_by_name():
"""Test tracker detection using name strings."""
result = detect_tracker("00:11:22:33:44:55", "My AirTag")
assert result["type"] == "airtag"
assert result["risk"] == "high"
# --- Route Tests ---
def test_get_interfaces_route(client, mocker):
"""Test the /interfaces endpoint with mocked system output."""
mock_run = mocker.patch("subprocess.run")
# Mocking hciconfig output for a Linux system
mock_run.return_value = MagicMock(
stdout="hci0:\tType: Primary Bus: USB\n\tBD Address: 00:11:22:33:44:55 ACL MTU: 1021:8 SCO MTU: 64:1\n\tUP RUNNING\n"
)
mocker.patch("platform.system", return_value="Linux")
mocker.patch("routes.bluetooth.check_tool", return_value=True)
response = client.get("/bt/interfaces")
data = response.get_json()
assert response.status_code == 200
assert data["interfaces"][0]["name"] == "hci0"
assert data["interfaces"][0]["status"] == "up"
assert data["tools"]["hcitool"] is True
def test_stop_scan_route(client, mock_app_module):
"""Test stopping a running scan process."""
mock_process = MagicMock()
mock_app_module.bt_process = mock_process
response = client.post("/bt/scan/stop")
assert response.status_code == 200
assert response.get_json()["status"] == "stopped"
mock_process.terminate.assert_called_once()
def test_enum_services_error_no_mac(client):
"""Test service enumeration validation."""
response = client.post("/bt/enum", json={})
assert response.status_code == 200
assert response.get_json()["status"] == "error"
def test_get_devices_route(client, mock_app_module):
"""Test retrieving the current device list from memory."""
mock_app_module.bt_devices = {"00:11:22:33:44:55": {"mac": "00:11:22:33:44:55", "name": "Test Device"}}
response = client.get("/bt/devices")
data = response.get_json()
assert response.status_code == 200
assert len(data["devices"]) == 1
assert data["devices"][0]["name"] == "Test Device"
def test_reload_oui_route(client, mocker):
"""Test the OUI database reload functionality."""
mocker.patch("routes.bluetooth.load_oui_database", return_value={"001122": "Test Corp"})
response = client.post("/bt/reload-oui")
data = response.get_json()
assert response.status_code == 200
assert data["status"] == "success"
assert data["entries"] > 0