332 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
			
		
		
	
	
			332 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
"""Test the Insteon All-Link Database APIs."""
 | 
						|
 | 
						|
import json
 | 
						|
from unittest.mock import patch
 | 
						|
 | 
						|
from pyinsteon import pub
 | 
						|
from pyinsteon.address import Address
 | 
						|
from pyinsteon.constants import ALDBStatus
 | 
						|
from pyinsteon.topics import ALDB_LINK_CHANGED, ALDB_STATUS_CHANGED
 | 
						|
import pytest
 | 
						|
 | 
						|
from homeassistant.components import insteon
 | 
						|
from homeassistant.components.insteon.api import async_load_api
 | 
						|
from homeassistant.components.insteon.api.aldb import (
 | 
						|
    ALDB_RECORD,
 | 
						|
    DEVICE_ADDRESS,
 | 
						|
    ID,
 | 
						|
    TYPE,
 | 
						|
)
 | 
						|
from homeassistant.components.insteon.api.device import INSTEON_DEVICE_NOT_FOUND
 | 
						|
from homeassistant.core import HomeAssistant
 | 
						|
 | 
						|
from .mock_devices import MockDevices
 | 
						|
 | 
						|
from tests.common import load_fixture
 | 
						|
from tests.typing import WebSocketGenerator
 | 
						|
 | 
						|
 | 
						|
@pytest.fixture(name="aldb_data", scope="module")
 | 
						|
def aldb_data_fixture():
 | 
						|
    """Load the controller state fixture data."""
 | 
						|
    return json.loads(load_fixture("insteon/aldb_data.json"))
 | 
						|
 | 
						|
 | 
						|
async def _setup(hass, hass_ws_client, aldb_data):
 | 
						|
    """Set up tests."""
 | 
						|
    ws_client = await hass_ws_client(hass)
 | 
						|
    devices = MockDevices()
 | 
						|
    await devices.async_load()
 | 
						|
    async_load_api(hass)
 | 
						|
    devices.fill_aldb("33.33.33", aldb_data)
 | 
						|
    return ws_client, devices
 | 
						|
 | 
						|
 | 
						|
def _compare_records(aldb_rec, dict_rec):
 | 
						|
    """Compare a record in the ALDB to the dictionary record."""
 | 
						|
    assert aldb_rec.is_in_use == dict_rec["in_use"]
 | 
						|
    assert aldb_rec.is_controller == (dict_rec["is_controller"])
 | 
						|
    assert not aldb_rec.is_high_water_mark
 | 
						|
    assert aldb_rec.group == dict_rec["group"]
 | 
						|
    assert aldb_rec.target == Address(dict_rec["target"])
 | 
						|
    assert aldb_rec.data1 == dict_rec["data1"]
 | 
						|
    assert aldb_rec.data2 == dict_rec["data2"]
 | 
						|
    assert aldb_rec.data3 == dict_rec["data3"]
 | 
						|
 | 
						|
 | 
						|
def _aldb_dict(mem_addr):
 | 
						|
    """Generate an ALDB record as a dictionary."""
 | 
						|
    return {
 | 
						|
        "mem_addr": mem_addr,
 | 
						|
        "in_use": True,
 | 
						|
        "is_controller": True,
 | 
						|
        "highwater": False,
 | 
						|
        "group": 100,
 | 
						|
        "target": "111111",
 | 
						|
        "data1": 101,
 | 
						|
        "data2": 102,
 | 
						|
        "data3": 103,
 | 
						|
        "dirty": True,
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
# This tests needs to be adjusted to remove lingering tasks
 | 
						|
@pytest.mark.parametrize("expected_lingering_tasks", [True])
 | 
						|
async def test_get_aldb(
 | 
						|
    hass: HomeAssistant, hass_ws_client: WebSocketGenerator, aldb_data
 | 
						|
) -> None:
 | 
						|
    """Test getting an Insteon device's All-Link Database."""
 | 
						|
    ws_client, devices = await _setup(hass, hass_ws_client, aldb_data)
 | 
						|
 | 
						|
    with patch.object(insteon.api.aldb, "devices", devices):
 | 
						|
        await ws_client.send_json(
 | 
						|
            {ID: 2, TYPE: "insteon/aldb/get", DEVICE_ADDRESS: "33.33.33"}
 | 
						|
        )
 | 
						|
        msg = await ws_client.receive_json()
 | 
						|
        result = msg["result"]
 | 
						|
 | 
						|
        assert len(result) == 5
 | 
						|
 | 
						|
 | 
						|
# This tests needs to be adjusted to remove lingering tasks
 | 
						|
@pytest.mark.parametrize("expected_lingering_tasks", [True])
 | 
						|
async def test_change_aldb_record(
 | 
						|
    hass: HomeAssistant, hass_ws_client: WebSocketGenerator, aldb_data
 | 
						|
) -> None:
 | 
						|
    """Test changing an Insteon device's All-Link Database record."""
 | 
						|
    ws_client, devices = await _setup(hass, hass_ws_client, aldb_data)
 | 
						|
    change_rec = _aldb_dict(4079)
 | 
						|
 | 
						|
    with patch.object(insteon.api.aldb, "devices", devices):
 | 
						|
        await ws_client.send_json(
 | 
						|
            {
 | 
						|
                ID: 2,
 | 
						|
                TYPE: "insteon/aldb/change",
 | 
						|
                DEVICE_ADDRESS: "33.33.33",
 | 
						|
                ALDB_RECORD: change_rec,
 | 
						|
            }
 | 
						|
        )
 | 
						|
        msg = await ws_client.receive_json()
 | 
						|
        assert msg["success"]
 | 
						|
        assert len(devices["33.33.33"].aldb.pending_changes) == 1
 | 
						|
        rec = devices["33.33.33"].aldb.pending_changes[4079]
 | 
						|
        _compare_records(rec, change_rec)
 | 
						|
 | 
						|
 | 
						|
# This tests needs to be adjusted to remove lingering tasks
 | 
						|
@pytest.mark.parametrize("expected_lingering_tasks", [True])
 | 
						|
async def test_create_aldb_record(
 | 
						|
    hass: HomeAssistant, hass_ws_client: WebSocketGenerator, aldb_data
 | 
						|
) -> None:
 | 
						|
    """Test creating a new Insteon All-Link Database record."""
 | 
						|
    ws_client, devices = await _setup(hass, hass_ws_client, aldb_data)
 | 
						|
    new_rec = _aldb_dict(4079)
 | 
						|
 | 
						|
    with patch.object(insteon.api.aldb, "devices", devices):
 | 
						|
        await ws_client.send_json(
 | 
						|
            {
 | 
						|
                ID: 2,
 | 
						|
                TYPE: "insteon/aldb/create",
 | 
						|
                DEVICE_ADDRESS: "33.33.33",
 | 
						|
                ALDB_RECORD: new_rec,
 | 
						|
            }
 | 
						|
        )
 | 
						|
        msg = await ws_client.receive_json()
 | 
						|
        assert msg["success"]
 | 
						|
        assert len(devices["33.33.33"].aldb.pending_changes) == 1
 | 
						|
        rec = devices["33.33.33"].aldb.pending_changes[-1]
 | 
						|
        _compare_records(rec, new_rec)
 | 
						|
 | 
						|
 | 
						|
# This tests needs to be adjusted to remove lingering tasks
 | 
						|
@pytest.mark.parametrize("expected_lingering_tasks", [True])
 | 
						|
async def test_write_aldb(
 | 
						|
    hass: HomeAssistant, hass_ws_client: WebSocketGenerator, aldb_data
 | 
						|
) -> None:
 | 
						|
    """Test writing an Insteon device's All-Link Database."""
 | 
						|
    ws_client, devices = await _setup(hass, hass_ws_client, aldb_data)
 | 
						|
 | 
						|
    with patch.object(insteon.api.aldb, "devices", devices):
 | 
						|
        await ws_client.send_json(
 | 
						|
            {
 | 
						|
                ID: 2,
 | 
						|
                TYPE: "insteon/aldb/write",
 | 
						|
                DEVICE_ADDRESS: "33.33.33",
 | 
						|
            }
 | 
						|
        )
 | 
						|
        msg = await ws_client.receive_json()
 | 
						|
        assert msg["success"]
 | 
						|
        assert devices["33.33.33"].aldb.async_write.call_count == 1
 | 
						|
        assert devices["33.33.33"].aldb.async_load.call_count == 1
 | 
						|
        assert devices.async_save.call_count == 1
 | 
						|
 | 
						|
 | 
						|
# This tests needs to be adjusted to remove lingering tasks
 | 
						|
@pytest.mark.parametrize("expected_lingering_tasks", [True])
 | 
						|
async def test_load_aldb(
 | 
						|
    hass: HomeAssistant, hass_ws_client: WebSocketGenerator, aldb_data
 | 
						|
) -> None:
 | 
						|
    """Test loading an Insteon device's All-Link Database."""
 | 
						|
    ws_client, devices = await _setup(hass, hass_ws_client, aldb_data)
 | 
						|
 | 
						|
    with patch.object(insteon.api.aldb, "devices", devices):
 | 
						|
        await ws_client.send_json(
 | 
						|
            {
 | 
						|
                ID: 2,
 | 
						|
                TYPE: "insteon/aldb/load",
 | 
						|
                DEVICE_ADDRESS: "AA.AA.AA",
 | 
						|
            }
 | 
						|
        )
 | 
						|
        msg = await ws_client.receive_json()
 | 
						|
        assert msg["success"]
 | 
						|
        assert devices["AA.AA.AA"].aldb.async_load.call_count == 1
 | 
						|
        assert devices.async_save.call_count == 1
 | 
						|
 | 
						|
 | 
						|
# This tests needs to be adjusted to remove lingering tasks
 | 
						|
@pytest.mark.parametrize("expected_lingering_tasks", [True])
 | 
						|
async def test_reset_aldb(
 | 
						|
    hass: HomeAssistant, hass_ws_client: WebSocketGenerator, aldb_data
 | 
						|
) -> None:
 | 
						|
    """Test resetting an Insteon device's All-Link Database."""
 | 
						|
    ws_client, devices = await _setup(hass, hass_ws_client, aldb_data)
 | 
						|
    record = _aldb_dict(4079)
 | 
						|
    devices["33.33.33"].aldb.modify(
 | 
						|
        mem_addr=record["mem_addr"],
 | 
						|
        in_use=record["in_use"],
 | 
						|
        group=record["group"],
 | 
						|
        controller=record["is_controller"],
 | 
						|
        target=record["target"],
 | 
						|
        data1=record["data1"],
 | 
						|
        data2=record["data2"],
 | 
						|
        data3=record["data3"],
 | 
						|
    )
 | 
						|
 | 
						|
    assert devices["33.33.33"].aldb.pending_changes
 | 
						|
    with patch.object(insteon.api.aldb, "devices", devices):
 | 
						|
        await ws_client.send_json(
 | 
						|
            {
 | 
						|
                ID: 2,
 | 
						|
                TYPE: "insteon/aldb/reset",
 | 
						|
                DEVICE_ADDRESS: "33.33.33",
 | 
						|
            }
 | 
						|
        )
 | 
						|
        msg = await ws_client.receive_json()
 | 
						|
        assert msg["success"]
 | 
						|
        assert not devices["33.33.33"].aldb.pending_changes
 | 
						|
 | 
						|
 | 
						|
# This tests needs to be adjusted to remove lingering tasks
 | 
						|
@pytest.mark.parametrize("expected_lingering_tasks", [True])
 | 
						|
async def test_default_links(
 | 
						|
    hass: HomeAssistant, hass_ws_client: WebSocketGenerator, aldb_data
 | 
						|
) -> None:
 | 
						|
    """Test getting an Insteon device's All-Link Database."""
 | 
						|
    ws_client, devices = await _setup(hass, hass_ws_client, aldb_data)
 | 
						|
 | 
						|
    with patch.object(insteon.api.aldb, "devices", devices):
 | 
						|
        await ws_client.send_json(
 | 
						|
            {
 | 
						|
                ID: 2,
 | 
						|
                TYPE: "insteon/aldb/add_default_links",
 | 
						|
                DEVICE_ADDRESS: "33.33.33",
 | 
						|
            }
 | 
						|
        )
 | 
						|
        msg = await ws_client.receive_json()
 | 
						|
        assert msg["success"]
 | 
						|
        assert devices["33.33.33"].async_add_default_links.call_count == 1
 | 
						|
        assert devices["33.33.33"].aldb.async_load.call_count == 1
 | 
						|
        assert devices.async_save.call_count == 1
 | 
						|
 | 
						|
 | 
						|
# This tests needs to be adjusted to remove lingering tasks
 | 
						|
@pytest.mark.parametrize("expected_lingering_tasks", [True])
 | 
						|
async def test_notify_on_aldb_status(
 | 
						|
    hass: HomeAssistant, hass_ws_client: WebSocketGenerator, aldb_data
 | 
						|
) -> None:
 | 
						|
    """Test getting an Insteon device's All-Link Database."""
 | 
						|
    ws_client, devices = await _setup(hass, hass_ws_client, aldb_data)
 | 
						|
 | 
						|
    with patch.object(insteon.api.aldb, "devices", devices):
 | 
						|
        await ws_client.send_json(
 | 
						|
            {
 | 
						|
                ID: 2,
 | 
						|
                TYPE: "insteon/aldb/notify",
 | 
						|
                DEVICE_ADDRESS: "33.33.33",
 | 
						|
            }
 | 
						|
        )
 | 
						|
        msg = await ws_client.receive_json()
 | 
						|
        assert msg["success"]
 | 
						|
 | 
						|
        pub.sendMessage(f"333333.{ALDB_STATUS_CHANGED}", status=ALDBStatus.LOADED)
 | 
						|
        msg = await ws_client.receive_json()
 | 
						|
        assert msg["event"]["type"] == "status_changed"
 | 
						|
        assert not msg["event"]["is_loading"]
 | 
						|
 | 
						|
 | 
						|
# This tests needs to be adjusted to remove lingering tasks
 | 
						|
@pytest.mark.parametrize("expected_lingering_tasks", [True])
 | 
						|
async def test_notify_on_aldb_record_added(
 | 
						|
    hass: HomeAssistant, hass_ws_client: WebSocketGenerator, aldb_data
 | 
						|
) -> None:
 | 
						|
    """Test getting an Insteon device's All-Link Database."""
 | 
						|
    ws_client, devices = await _setup(hass, hass_ws_client, aldb_data)
 | 
						|
 | 
						|
    with patch.object(insteon.api.aldb, "devices", devices):
 | 
						|
        await ws_client.send_json(
 | 
						|
            {
 | 
						|
                ID: 2,
 | 
						|
                TYPE: "insteon/aldb/notify",
 | 
						|
                DEVICE_ADDRESS: "33.33.33",
 | 
						|
            }
 | 
						|
        )
 | 
						|
        msg = await ws_client.receive_json()
 | 
						|
        assert msg["success"]
 | 
						|
 | 
						|
        pub.sendMessage(
 | 
						|
            f"333333.{ALDB_LINK_CHANGED}",
 | 
						|
            record="some record",
 | 
						|
            sender=Address("11.11.11"),
 | 
						|
            deleted=False,
 | 
						|
        )
 | 
						|
        msg = await ws_client.receive_json()
 | 
						|
        assert msg["event"]["type"] == "record_loaded"
 | 
						|
 | 
						|
 | 
						|
# This tests needs to be adjusted to remove lingering tasks
 | 
						|
@pytest.mark.parametrize("expected_lingering_tasks", [True])
 | 
						|
async def test_bad_address(
 | 
						|
    hass: HomeAssistant, hass_ws_client: WebSocketGenerator, aldb_data
 | 
						|
) -> None:
 | 
						|
    """Test for a bad Insteon address."""
 | 
						|
    ws_client, _ = await _setup(hass, hass_ws_client, aldb_data)
 | 
						|
    record = _aldb_dict(0)
 | 
						|
 | 
						|
    ws_id = 0
 | 
						|
    for call in ["get", "write", "load", "reset", "add_default_links", "notify"]:
 | 
						|
        ws_id += 1
 | 
						|
        await ws_client.send_json(
 | 
						|
            {
 | 
						|
                ID: ws_id,
 | 
						|
                TYPE: f"insteon/aldb/{call}",
 | 
						|
                DEVICE_ADDRESS: "99.99.99",
 | 
						|
            }
 | 
						|
        )
 | 
						|
        msg = await ws_client.receive_json()
 | 
						|
        assert not msg["success"]
 | 
						|
        assert msg["error"]["message"] == INSTEON_DEVICE_NOT_FOUND
 | 
						|
 | 
						|
    for call in ["change", "create"]:
 | 
						|
        ws_id += 1
 | 
						|
        await ws_client.send_json(
 | 
						|
            {
 | 
						|
                ID: ws_id,
 | 
						|
                TYPE: f"insteon/aldb/{call}",
 | 
						|
                DEVICE_ADDRESS: "99.99.99",
 | 
						|
                ALDB_RECORD: record,
 | 
						|
            }
 | 
						|
        )
 | 
						|
        msg = await ws_client.receive_json()
 | 
						|
        assert not msg["success"]
 | 
						|
        assert msg["error"]["message"] == INSTEON_DEVICE_NOT_FOUND
 |