core/tests/components/bluetooth/test_diagnostics.py

281 lines
11 KiB
Python

"""Test bluetooth diagnostics."""
from unittest.mock import ANY, patch
from bleak.backends.scanner import BLEDevice
from homeassistant.components import bluetooth
from homeassistant.components.bluetooth.const import DEFAULT_ADDRESS
from . import generate_advertisement_data, inject_advertisement
from tests.common import MockConfigEntry
from tests.components.diagnostics import get_diagnostics_for_config_entry
async def test_diagnostics(
hass, hass_client, mock_bleak_scanner_start, enable_bluetooth, two_adapters
):
"""Test we can setup and unsetup bluetooth with multiple adapters."""
# Normally we do not want to patch our classes, but since bleak will import
# a different scanner based on the operating system, we need to patch here
# because we cannot import the scanner class directly without it throwing an
# error if the test is not running on linux since we won't have the correct
# deps installed when testing on MacOS.
with patch(
"homeassistant.components.bluetooth.scanner.HaScanner.discovered_devices",
[BLEDevice(name="x", rssi=-60, address="44:44:33:11:23:45")],
), patch(
"homeassistant.components.bluetooth.diagnostics.platform.system",
return_value="Linux",
), patch(
"homeassistant.components.bluetooth.diagnostics.get_dbus_managed_objects",
return_value={
"org.bluez": {
"/org/bluez/hci0": {
"org.bluez.Adapter1": {
"Name": "BlueZ 5.63",
"Alias": "BlueZ 5.63",
"Modalias": "usb:v1D6Bp0246d0540",
"Discovering": False,
},
"org.bluez.AdvertisementMonitorManager1": {
"SupportedMonitorTypes": ["or_patterns"],
"SupportedFeatures": [],
},
}
}
},
):
entry1 = MockConfigEntry(
domain=bluetooth.DOMAIN, data={}, unique_id="00:00:00:00:00:01"
)
entry1.add_to_hass(hass)
entry2 = MockConfigEntry(
domain=bluetooth.DOMAIN, data={}, unique_id="00:00:00:00:00:02"
)
entry2.add_to_hass(hass)
assert await hass.config_entries.async_setup(entry1.entry_id)
await hass.async_block_till_done()
assert await hass.config_entries.async_setup(entry2.entry_id)
await hass.async_block_till_done()
diag = await get_diagnostics_for_config_entry(hass, hass_client, entry1)
assert diag == {
"adapters": {
"hci0": {
"address": "00:00:00:00:00:01",
"hw_version": "usbid:1234",
"passive_scan": False,
"sw_version": "BlueZ 4.63",
},
"hci1": {
"address": "00:00:00:00:00:02",
"hw_version": "usbid:1234",
"passive_scan": True,
"sw_version": "BlueZ 4.63",
},
},
"dbus": {
"org.bluez": {
"/org/bluez/hci0": {
"org.bluez.Adapter1": {
"Alias": "BlueZ " "5.63",
"Discovering": False,
"Modalias": "usb:v1D6Bp0246d0540",
"Name": "BlueZ " "5.63",
},
"org.bluez.AdvertisementMonitorManager1": {
"SupportedFeatures": [],
"SupportedMonitorTypes": ["or_patterns"],
},
}
}
},
"manager": {
"adapters": {
"hci0": {
"address": "00:00:00:00:00:01",
"hw_version": "usbid:1234",
"passive_scan": False,
"sw_version": "BlueZ 4.63",
},
"hci1": {
"address": "00:00:00:00:00:02",
"hw_version": "usbid:1234",
"passive_scan": True,
"sw_version": "BlueZ 4.63",
},
},
"advertisement_tracker": {
"intervals": {},
"sources": {},
"timings": {},
},
"connectable_history": [],
"all_history": [],
"scanners": [
{
"adapter": "hci0",
"discovered_devices": [
{"address": "44:44:33:11:23:45", "name": "x"}
],
"last_detection": ANY,
"name": "hci0 (00:00:00:00:00:01)",
"source": "00:00:00:00:00:01",
"start_time": ANY,
"type": "HaScanner",
},
{
"adapter": "hci0",
"discovered_devices": [
{"address": "44:44:33:11:23:45", "name": "x"}
],
"last_detection": ANY,
"name": "hci0 (00:00:00:00:00:01)",
"source": "00:00:00:00:00:01",
"start_time": ANY,
"type": "HaScanner",
},
{
"adapter": "hci1",
"discovered_devices": [
{"address": "44:44:33:11:23:45", "name": "x"}
],
"last_detection": ANY,
"name": "hci1 (00:00:00:00:00:02)",
"source": "00:00:00:00:00:02",
"start_time": ANY,
"type": "HaScanner",
},
],
},
}
async def test_diagnostics_macos(
hass, hass_client, mock_bleak_scanner_start, mock_bluetooth_adapters, macos_adapter
):
"""Test we can setup and unsetup bluetooth with multiple adapters."""
# Normally we do not want to patch our classes, but since bleak will import
# a different scanner based on the operating system, we need to patch here
# because we cannot import the scanner class directly without it throwing an
# error if the test is not running on linux since we won't have the correct
# deps installed when testing on MacOS.
switchbot_device = BLEDevice("44:44:33:11:23:45", "wohand")
switchbot_adv = generate_advertisement_data(
local_name="wohand", service_uuids=[], manufacturer_data={1: b"\x01"}
)
with patch(
"homeassistant.components.bluetooth.scanner.HaScanner.discovered_devices",
[BLEDevice(name="x", rssi=-60, address="44:44:33:11:23:45")],
), patch(
"homeassistant.components.bluetooth.diagnostics.platform.system",
return_value="Darwin",
), patch(
"homeassistant.components.bluetooth.diagnostics.get_dbus_managed_objects",
return_value={},
):
entry1 = MockConfigEntry(
domain=bluetooth.DOMAIN,
data={},
title="Core Bluetooth",
unique_id=DEFAULT_ADDRESS,
)
entry1.add_to_hass(hass)
assert await hass.config_entries.async_setup(entry1.entry_id)
await hass.async_block_till_done()
inject_advertisement(hass, switchbot_device, switchbot_adv)
diag = await get_diagnostics_for_config_entry(hass, hass_client, entry1)
assert diag == {
"adapters": {
"Core Bluetooth": {
"address": "00:00:00:00:00:00",
"passive_scan": False,
"sw_version": ANY,
}
},
"manager": {
"adapters": {
"Core Bluetooth": {
"address": "00:00:00:00:00:00",
"passive_scan": False,
"sw_version": ANY,
}
},
"advertisement_tracker": {
"intervals": {},
"sources": {"44:44:33:11:23:45": "local"},
"timings": {"44:44:33:11:23:45": [ANY]},
},
"connectable_history": [
{
"address": "44:44:33:11:23:45",
"advertisement": [
"wohand",
{"1": {"__type": "<class " "'bytes'>", "repr": "b'\\x01'"}},
{},
[],
-127,
-127,
[[]],
],
"connectable": True,
"manufacturer_data": {
"1": {"__type": "<class " "'bytes'>", "repr": "b'\\x01'"}
},
"name": "wohand",
"rssi": -127,
"service_data": {},
"service_uuids": [],
"source": "local",
"time": ANY,
}
],
"all_history": [
{
"address": "44:44:33:11:23:45",
"advertisement": [
"wohand",
{"1": {"__type": "<class " "'bytes'>", "repr": "b'\\x01'"}},
{},
[],
-127,
-127,
[[]],
],
"connectable": True,
"manufacturer_data": {
"1": {"__type": "<class " "'bytes'>", "repr": "b'\\x01'"}
},
"name": "wohand",
"rssi": -127,
"service_data": {},
"service_uuids": [],
"source": "local",
"time": ANY,
}
],
"scanners": [
{
"adapter": "Core Bluetooth",
"discovered_devices": [
{"address": "44:44:33:11:23:45", "name": "x"}
],
"last_detection": ANY,
"name": "Core Bluetooth",
"source": "Core Bluetooth",
"start_time": ANY,
"type": "HaScanner",
}
],
},
}