mirror of
https://github.com/smittix/intercept.git
synced 2026-06-14 16:43:38 -07:00
Merge remote-tracking branch 'upstream/main'
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
"""Tests for HackRF command builder."""
|
||||
|
||||
from utils.sdr.base import SDRDevice, SDRType
|
||||
from utils.sdr.hackrf import HackRFCommandBuilder
|
||||
|
||||
|
||||
def _make_device(serial: str = 'abc123') -> SDRDevice:
|
||||
return SDRDevice(
|
||||
sdr_type=SDRType.HACKRF,
|
||||
index=0,
|
||||
name='HackRF One',
|
||||
serial=serial,
|
||||
driver='hackrf',
|
||||
capabilities=HackRFCommandBuilder.CAPABILITIES,
|
||||
)
|
||||
|
||||
|
||||
class TestHackRFCapabilities:
|
||||
def test_gain_max_reflects_combined_lna_vga(self):
|
||||
"""gain_max should be LNA(40) + VGA(62) = 102."""
|
||||
assert HackRFCommandBuilder.CAPABILITIES.gain_max == 102.0
|
||||
|
||||
def test_frequency_range(self):
|
||||
caps = HackRFCommandBuilder.CAPABILITIES
|
||||
assert caps.freq_min_mhz == 1.0
|
||||
assert caps.freq_max_mhz == 6000.0
|
||||
|
||||
def test_tx_capable(self):
|
||||
assert HackRFCommandBuilder.CAPABILITIES.tx_capable is True
|
||||
|
||||
|
||||
class TestSplitGain:
|
||||
def test_low_gain_all_to_lna(self):
|
||||
builder = HackRFCommandBuilder()
|
||||
lna, vga = builder._split_gain(30)
|
||||
assert lna == 30
|
||||
assert vga == 0
|
||||
|
||||
def test_gain_at_lna_max(self):
|
||||
builder = HackRFCommandBuilder()
|
||||
lna, vga = builder._split_gain(40)
|
||||
assert lna == 40
|
||||
assert vga == 0
|
||||
|
||||
def test_high_gain_splits_across_stages(self):
|
||||
builder = HackRFCommandBuilder()
|
||||
lna, vga = builder._split_gain(80)
|
||||
assert lna == 40
|
||||
assert vga == 40
|
||||
|
||||
def test_max_combined_gain(self):
|
||||
builder = HackRFCommandBuilder()
|
||||
lna, vga = builder._split_gain(102)
|
||||
assert lna == 40
|
||||
assert vga == 62
|
||||
|
||||
|
||||
class TestBuildAdsbCommand:
|
||||
def test_contains_soapysdr_device_type(self):
|
||||
builder = HackRFCommandBuilder()
|
||||
cmd = builder.build_adsb_command(_make_device(), gain=40)
|
||||
assert '--device-type' in cmd
|
||||
assert 'soapysdr' in cmd
|
||||
|
||||
def test_includes_serial_in_device_string(self):
|
||||
builder = HackRFCommandBuilder()
|
||||
cmd = builder.build_adsb_command(_make_device(serial='deadbeef'), gain=40)
|
||||
device_idx = cmd.index('--device')
|
||||
assert 'deadbeef' in cmd[device_idx + 1]
|
||||
|
||||
|
||||
class TestBuildIQCaptureCommand:
|
||||
def test_outputs_cu8_to_stdout(self):
|
||||
builder = HackRFCommandBuilder()
|
||||
cmd = builder.build_iq_capture_command(
|
||||
_make_device(), frequency_mhz=100.0, sample_rate=2048000, gain=40
|
||||
)
|
||||
assert '-F' in cmd
|
||||
assert 'CU8' in cmd
|
||||
assert cmd[-1] == '-'
|
||||
|
||||
def test_gain_split_in_command(self):
|
||||
builder = HackRFCommandBuilder()
|
||||
cmd = builder.build_iq_capture_command(
|
||||
_make_device(), frequency_mhz=100.0, gain=80
|
||||
)
|
||||
gain_idx = cmd.index('-g')
|
||||
assert cmd[gain_idx + 1] == 'LNA=40,VGA=40'
|
||||
@@ -1,9 +1,20 @@
|
||||
"""Tests for RTL-SDR detection parsing."""
|
||||
"""Tests for SDR detection parsing (RTL-SDR and HackRF)."""
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
import utils.sdr.detection as detection_mod
|
||||
from utils.sdr.base import SDRType
|
||||
from utils.sdr.detection import detect_rtlsdr_devices
|
||||
from utils.sdr.detection import detect_hackrf_devices, detect_rtlsdr_devices
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _clear_detection_caches():
|
||||
"""Reset detection caches before each test."""
|
||||
detection_mod._hackrf_cache = []
|
||||
detection_mod._hackrf_cache_ts = 0.0
|
||||
yield
|
||||
|
||||
|
||||
@patch('utils.sdr.detection._check_tool', return_value=True)
|
||||
@@ -44,3 +55,87 @@ def test_detect_rtlsdr_devices_uses_replace_decode_mode(mock_run, _mock_check_to
|
||||
assert kwargs["text"] is True
|
||||
assert kwargs["encoding"] == "utf-8"
|
||||
assert kwargs["errors"] == "replace"
|
||||
|
||||
|
||||
# ---- HackRF detection tests ----
|
||||
|
||||
HACKRF_INFO_OUTPUT = (
|
||||
"hackrf_info version: 2024.02.1\n"
|
||||
"libhackrf version: 2024.02.1 (0.9)\n"
|
||||
"Found HackRF\n"
|
||||
"Index: 0\n"
|
||||
"Serial number: 0000000000000000a06063c8234e925f\n"
|
||||
"Board ID Number: 2 (HackRF One)\n"
|
||||
"Firmware Version: 2024.02.1 (API:1.08)\n"
|
||||
"Part ID Number: 0xa000cb3c 0x00614764\n"
|
||||
"Hardware Revision: r9\n"
|
||||
"Hardware supported by installed firmware:\n"
|
||||
" HackRF One\n"
|
||||
)
|
||||
|
||||
|
||||
@patch('utils.sdr.detection._check_tool', return_value=True)
|
||||
@patch('utils.sdr.detection.subprocess.run')
|
||||
def test_detect_hackrf_from_stdout(mock_run, _mock_check_tool):
|
||||
"""Parse HackRF device info from stdout."""
|
||||
mock_result = MagicMock()
|
||||
mock_result.stdout = HACKRF_INFO_OUTPUT
|
||||
mock_result.stderr = ""
|
||||
mock_run.return_value = mock_result
|
||||
|
||||
devices = detect_hackrf_devices()
|
||||
|
||||
assert len(devices) == 1
|
||||
assert devices[0].sdr_type == SDRType.HACKRF
|
||||
assert devices[0].name == "HackRF One"
|
||||
assert devices[0].serial == "0000000000000000a06063c8234e925f"
|
||||
assert devices[0].index == 0
|
||||
|
||||
|
||||
@patch('utils.sdr.detection._check_tool', return_value=True)
|
||||
@patch('utils.sdr.detection.subprocess.run')
|
||||
def test_detect_hackrf_from_stderr(mock_run, _mock_check_tool):
|
||||
"""Parse HackRF device info when output goes to stderr (newer firmware)."""
|
||||
mock_result = MagicMock()
|
||||
mock_result.stdout = ""
|
||||
mock_result.stderr = HACKRF_INFO_OUTPUT
|
||||
mock_run.return_value = mock_result
|
||||
|
||||
devices = detect_hackrf_devices()
|
||||
|
||||
assert len(devices) == 1
|
||||
assert devices[0].sdr_type == SDRType.HACKRF
|
||||
assert devices[0].name == "HackRF One"
|
||||
assert devices[0].serial == "0000000000000000a06063c8234e925f"
|
||||
|
||||
|
||||
@patch('utils.sdr.detection._check_tool', return_value=True)
|
||||
@patch('utils.sdr.detection.subprocess.run')
|
||||
def test_detect_hackrf_nonzero_exit_with_valid_output(mock_run, _mock_check_tool):
|
||||
"""Parse HackRF info even when hackrf_info exits non-zero (device busy)."""
|
||||
mock_result = MagicMock()
|
||||
mock_result.returncode = 1
|
||||
mock_result.stdout = ""
|
||||
mock_result.stderr = HACKRF_INFO_OUTPUT
|
||||
mock_run.return_value = mock_result
|
||||
|
||||
devices = detect_hackrf_devices()
|
||||
|
||||
assert len(devices) == 1
|
||||
assert devices[0].name == "HackRF One"
|
||||
|
||||
|
||||
@patch('utils.sdr.detection._check_tool', return_value=True)
|
||||
@patch('utils.sdr.detection.subprocess.run')
|
||||
def test_detect_hackrf_fallback_no_serial(mock_run, _mock_check_tool):
|
||||
"""Fallback detection when serial is missing but 'Found HackRF' present."""
|
||||
mock_result = MagicMock()
|
||||
mock_result.stdout = "Found HackRF\nBoard ID Number: 2 (HackRF One)\n"
|
||||
mock_result.stderr = ""
|
||||
mock_run.return_value = mock_result
|
||||
|
||||
devices = detect_hackrf_devices()
|
||||
|
||||
assert len(devices) == 1
|
||||
assert devices[0].name == "HackRF One"
|
||||
assert devices[0].serial == "Unknown"
|
||||
|
||||
Reference in New Issue
Block a user