mirror of
https://github.com/smittix/intercept.git
synced 2026-04-24 06:40:00 -07:00
Merge pull request #36 from JonanOribe/main
Thanks for the contribution! The Bluetooth tests look great and will help ensure stability as we continue development.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -8,6 +8,7 @@ env/
|
||||
venv/
|
||||
.venv/
|
||||
ENV/
|
||||
uv.lock
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
|
||||
@@ -40,6 +40,7 @@ Issues = "https://github.com/smittix/intercept/issues"
|
||||
dev = [
|
||||
"pytest>=7.0.0",
|
||||
"pytest-cov>=4.0.0",
|
||||
"pytest-mock>=3.15.1",
|
||||
"ruff>=0.1.0",
|
||||
"black>=23.0.0",
|
||||
"mypy>=1.0.0",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
# Testing
|
||||
pytest>=7.0.0
|
||||
pytest-cov>=4.0.0
|
||||
pytest-mock>=3.15.1
|
||||
|
||||
# Code quality
|
||||
ruff>=0.1.0
|
||||
|
||||
129
tests/test_bluetooth.py
Normal file
129
tests/test_bluetooth.py
Normal file
@@ -0,0 +1,129 @@
|
||||
import pytest
|
||||
import json
|
||||
import subprocess
|
||||
from unittest.mock import MagicMock, patch
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user