Files
soundtower-controller/tests/test_probe.py
T
lda Verified 038e152bbc
Checks / tests (ubuntu-latest, 3.11) (push) Canceled after 0s
Checks / tests (ubuntu-latest, 3.14) (push) Canceled after 0s
Checks / tests (windows-latest, 3.11) (push) Canceled after 0s
Checks / tests (windows-latest, 3.14) (push) Canceled after 0s
Checks / package (push) Canceled after 0s
Add MX-T40 BLE desktop controller and protocol documentation
2026-10-25 04:43:47 +07:00

89 lines
3.3 KiB
Python

"""Model the named overloads exported by Python/WinRT, not C# overloads."""
import asyncio
import contextlib
import io
import sys
import types
import unittest
from unittest.mock import patch
from controller.probe import SPP_UUID, check_channel, probe
class ProbeTests(unittest.TestCase):
def test_projected_overloads_and_resource_cleanup(self):
closed = []
selector = "paired Bluetooth selector"
service = types.SimpleNamespace(
service_id=types.SimpleNamespace(uuid=SPP_UUID),
connection_host_name=types.SimpleNamespace(raw_name="speaker-host"),
connection_service_name="1",
close=lambda: closed.append("service"),
)
async def get_services(cache_mode):
self.assertEqual(cache_mode, 1)
return types.SimpleNamespace(error=0, services=[service])
async def from_id(device_id):
self.assertEqual(device_id, "device-id")
return types.SimpleNamespace(
bluetooth_address=0x123456789ABC,
get_rfcomm_services_with_cache_mode_async=get_services,
close=lambda: closed.append("device"),
)
async def find_filtered(value):
self.assertEqual(value, selector)
return [types.SimpleNamespace(name="MX-T40", id="device-id")]
def wrong_overload(value):
# The installed projection treats this argument as DeviceClass.
raise TypeError("'str' object cannot be interpreted as an integer")
bluetooth = types.SimpleNamespace(
BluetoothCacheMode=types.SimpleNamespace(UNCACHED=1),
BluetoothDevice=types.SimpleNamespace(
get_device_selector_from_pairing_state=lambda paired: selector,
from_id_async=from_id,
),
)
enumeration = types.SimpleNamespace(
DeviceInformation=types.SimpleNamespace(
find_all_async=wrong_overload,
find_all_async_aqs_filter=find_filtered,
)
)
with (
patch.dict(
sys.modules,
{
"winrt.windows.devices.bluetooth": bluetooth,
"winrt.windows.devices.enumeration": enumeration,
},
),
contextlib.redirect_stdout(io.StringIO()) as output,
):
result = asyncio.run(probe("MX-T40"))
self.assertEqual(result, 0)
self.assertIn("SPP service found: True", output.getvalue())
self.assertEqual(closed, ["service", "device"])
def test_direct_channel_connects_without_sending(self):
from unittest.mock import MagicMock
stream = MagicMock()
with (
patch("controller.probe.socket.socket") as create,
patch("controller.probe.socket.AF_BLUETOOTH", 32, create=True),
patch("controller.probe.socket.BTPROTO_RFCOMM", 3, create=True),
):
create.return_value.__enter__.return_value = stream
check_channel("12:34:56:78:9A:BC", 1)
stream.connect.assert_called_once_with(("12:34:56:78:9A:BC", 1))
stream.settimeout.assert_called_once_with(10)
stream.send.assert_not_called()
stream.sendall.assert_not_called()
create.return_value.__exit__.assert_called_once()