Add slots to core EventBus (#95856)

This commit is contained in:
J. Nick Koston 2023-07-05 11:47:24 -05:00 committed by GitHub
parent 20dc9203dd
commit dc5ee71d7a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 217 additions and 411 deletions

View File

@ -973,6 +973,8 @@ _FilterableJobType = tuple[
class EventBus:
"""Allow the firing of and listening for events."""
__slots__ = ("_listeners", "_match_all_listeners", "_hass")
def __init__(self, hass: HomeAssistant) -> None:
"""Initialize a new event bus."""
self._listeners: dict[str, list[_FilterableJobType]] = {}

View File

@ -1,15 +1,13 @@
"""The tests for the Datadog component."""
from unittest import mock
from unittest.mock import MagicMock, patch
from unittest.mock import patch
import homeassistant.components.datadog as datadog
from homeassistant.const import (
EVENT_LOGBOOK_ENTRY,
EVENT_STATE_CHANGED,
STATE_OFF,
STATE_ON,
)
import homeassistant.core as ha
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
@ -27,7 +25,6 @@ async def test_invalid_config(hass: HomeAssistant) -> None:
async def test_datadog_setup_full(hass: HomeAssistant) -> None:
"""Test setup with all data."""
config = {datadog.DOMAIN: {"host": "host", "port": 123, "rate": 1, "prefix": "foo"}}
hass.bus.listen = MagicMock()
with patch("homeassistant.components.datadog.initialize") as mock_init, patch(
"homeassistant.components.datadog.statsd"
@ -37,15 +34,9 @@ async def test_datadog_setup_full(hass: HomeAssistant) -> None:
assert mock_init.call_count == 1
assert mock_init.call_args == mock.call(statsd_host="host", statsd_port=123)
assert hass.bus.listen.called
assert hass.bus.listen.call_args_list[0][0][0] == EVENT_LOGBOOK_ENTRY
assert hass.bus.listen.call_args_list[1][0][0] == EVENT_STATE_CHANGED
async def test_datadog_setup_defaults(hass: HomeAssistant) -> None:
"""Test setup with defaults."""
hass.bus.listen = mock.MagicMock()
with patch("homeassistant.components.datadog.initialize") as mock_init, patch(
"homeassistant.components.datadog.statsd"
):
@ -63,13 +54,10 @@ async def test_datadog_setup_defaults(hass: HomeAssistant) -> None:
assert mock_init.call_count == 1
assert mock_init.call_args == mock.call(statsd_host="host", statsd_port=8125)
assert hass.bus.listen.called
async def test_logbook_entry(hass: HomeAssistant) -> None:
"""Test event listener."""
hass.bus.listen = mock.MagicMock()
with patch("homeassistant.components.datadog.initialize"), patch(
"homeassistant.components.datadog.statsd"
) as mock_statsd:
@ -79,16 +67,14 @@ async def test_logbook_entry(hass: HomeAssistant) -> None:
{datadog.DOMAIN: {"host": "host", "rate": datadog.DEFAULT_RATE}},
)
assert hass.bus.listen.called
handler_method = hass.bus.listen.call_args_list[0][0][1]
event = {
"domain": "automation",
"entity_id": "sensor.foo.bar",
"message": "foo bar biz",
"name": "triggered something",
}
handler_method(mock.MagicMock(data=event))
hass.bus.async_fire(EVENT_LOGBOOK_ENTRY, event)
await hass.async_block_till_done()
assert mock_statsd.event.call_count == 1
assert mock_statsd.event.call_args == mock.call(
@ -102,8 +88,6 @@ async def test_logbook_entry(hass: HomeAssistant) -> None:
async def test_state_changed(hass: HomeAssistant) -> None:
"""Test event listener."""
hass.bus.listen = mock.MagicMock()
with patch("homeassistant.components.datadog.initialize"), patch(
"homeassistant.components.datadog.statsd"
) as mock_statsd:
@ -119,9 +103,6 @@ async def test_state_changed(hass: HomeAssistant) -> None:
},
)
assert hass.bus.listen.called
handler_method = hass.bus.listen.call_args_list[1][0][1]
valid = {"1": 1, "1.0": 1.0, STATE_ON: 1, STATE_OFF: 0}
attributes = {"elevation": 3.2, "temperature": 5.0, "up": True, "down": False}
@ -129,12 +110,12 @@ async def test_state_changed(hass: HomeAssistant) -> None:
for in_, out in valid.items():
state = mock.MagicMock(
domain="sensor",
entity_id="sensor.foo.bar",
entity_id="sensor.foobar",
state=in_,
attributes=attributes,
)
handler_method(mock.MagicMock(data={"new_state": state}))
hass.states.async_set(state.entity_id, state.state, state.attributes)
await hass.async_block_till_done()
assert mock_statsd.gauge.call_count == 5
for attribute, value in attributes.items():
@ -160,7 +141,6 @@ async def test_state_changed(hass: HomeAssistant) -> None:
mock_statsd.gauge.reset_mock()
for invalid in ("foo", "", object):
handler_method(
mock.MagicMock(data={"new_state": ha.State("domain.test", invalid, {})})
)
hass.states.async_set("domain.test", invalid, {})
await hass.async_block_till_done()
assert not mock_statsd.gauge.called

View File

@ -8,7 +8,11 @@ from homeassistant.components.ffmpeg import (
SERVICE_START,
SERVICE_STOP,
)
from homeassistant.const import ATTR_ENTITY_ID
from homeassistant.const import (
ATTR_ENTITY_ID,
EVENT_HOMEASSISTANT_START,
EVENT_HOMEASSISTANT_STOP,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.setup import async_setup_component, setup_component
@ -54,7 +58,7 @@ class MockFFmpegDev(ffmpeg.FFmpegBase):
self.hass = hass
self.entity_id = entity_id
self.ffmpeg = MagicMock
self.ffmpeg = MagicMock()
self.called_stop = False
self.called_start = False
self.called_restart = False
@ -104,12 +108,18 @@ async def test_setup_component_test_register(hass: HomeAssistant) -> None:
with assert_setup_component(1):
await async_setup_component(hass, ffmpeg.DOMAIN, {ffmpeg.DOMAIN: {}})
hass.bus.async_listen_once = MagicMock()
ffmpeg_dev = MockFFmpegDev(hass)
ffmpeg_dev._async_stop_ffmpeg = AsyncMock()
ffmpeg_dev._async_start_ffmpeg = AsyncMock()
await ffmpeg_dev.async_added_to_hass()
assert hass.bus.async_listen_once.called
assert hass.bus.async_listen_once.call_count == 2
hass.bus.async_fire(EVENT_HOMEASSISTANT_START)
await hass.async_block_till_done()
assert len(ffmpeg_dev._async_start_ffmpeg.mock_calls) == 2
hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
await hass.async_block_till_done()
assert len(ffmpeg_dev._async_stop_ffmpeg.mock_calls) == 2
async def test_setup_component_test_register_no_startup(hass: HomeAssistant) -> None:
@ -117,12 +127,18 @@ async def test_setup_component_test_register_no_startup(hass: HomeAssistant) ->
with assert_setup_component(1):
await async_setup_component(hass, ffmpeg.DOMAIN, {ffmpeg.DOMAIN: {}})
hass.bus.async_listen_once = MagicMock()
ffmpeg_dev = MockFFmpegDev(hass, False)
ffmpeg_dev._async_stop_ffmpeg = AsyncMock()
ffmpeg_dev._async_start_ffmpeg = AsyncMock()
await ffmpeg_dev.async_added_to_hass()
assert hass.bus.async_listen_once.called
assert hass.bus.async_listen_once.call_count == 1
hass.bus.async_fire(EVENT_HOMEASSISTANT_START)
await hass.async_block_till_done()
assert len(ffmpeg_dev._async_start_ffmpeg.mock_calls) == 1
hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
await hass.async_block_till_done()
assert len(ffmpeg_dev._async_stop_ffmpeg.mock_calls) == 2
async def test_setup_component_test_service_start(hass: HomeAssistant) -> None:

View File

@ -8,8 +8,7 @@ import pytest
import homeassistant.components.google_pubsub as google_pubsub
from homeassistant.components.google_pubsub import DateTimeJSONEncoder as victim
from homeassistant.const import EVENT_STATE_CHANGED
from homeassistant.core import HomeAssistant, split_entity_id
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
GOOGLE_PUBSUB_PATH = "homeassistant.components.google_pubsub"
@ -60,9 +59,8 @@ def mock_is_file_fixture():
@pytest.fixture(autouse=True)
def mock_bus_and_json(hass, monkeypatch):
def mock_json(hass, monkeypatch):
"""Mock the event bus listener and os component."""
hass.bus.listen = mock.MagicMock()
monkeypatch.setattr(
f"{GOOGLE_PUBSUB_PATH}.json.dumps", mock.Mock(return_value=mock.MagicMock())
)
@ -80,8 +78,6 @@ async def test_minimal_config(hass: HomeAssistant, mock_client) -> None:
}
assert await async_setup_component(hass, google_pubsub.DOMAIN, config)
await hass.async_block_till_done()
assert hass.bus.listen.called
assert hass.bus.listen.call_args_list[0][0][0] == EVENT_STATE_CHANGED
assert mock_client.from_service_account_json.call_count == 1
assert mock_client.from_service_account_json.call_args[0][0] == os.path.join(
hass.config.config_dir, "creds"
@ -107,27 +103,12 @@ async def test_full_config(hass: HomeAssistant, mock_client) -> None:
}
assert await async_setup_component(hass, google_pubsub.DOMAIN, config)
await hass.async_block_till_done()
assert hass.bus.listen.called
assert hass.bus.listen.call_args_list[0][0][0] == EVENT_STATE_CHANGED
assert mock_client.from_service_account_json.call_count == 1
assert mock_client.from_service_account_json.call_args[0][0] == os.path.join(
hass.config.config_dir, "creds"
)
def make_event(entity_id):
"""Make a mock event for test."""
domain = split_entity_id(entity_id)[0]
state = mock.MagicMock(
state="not blank",
domain=domain,
entity_id=entity_id,
object_id="entity",
attributes={},
)
return mock.MagicMock(data={"new_state": state}, time_fired=12345)
async def _setup(hass, filter_config):
"""Shared set up for filtering tests."""
config = {
@ -140,12 +121,11 @@ async def _setup(hass, filter_config):
}
assert await async_setup_component(hass, google_pubsub.DOMAIN, config)
await hass.async_block_till_done()
return hass.bus.listen.call_args_list[0][0][1]
async def test_allowlist(hass: HomeAssistant, mock_client) -> None:
"""Test an allowlist only config."""
handler_method = await _setup(
await _setup(
hass,
{
"include_domains": ["light"],
@ -165,8 +145,8 @@ async def test_allowlist(hass: HomeAssistant, mock_client) -> None:
]
for test in tests:
event = make_event(test.id)
handler_method(event)
hass.states.async_set(test.id, "not blank")
await hass.async_block_till_done()
was_called = publish_client.publish.call_count == 1
assert test.should_pass == was_called
@ -175,7 +155,7 @@ async def test_allowlist(hass: HomeAssistant, mock_client) -> None:
async def test_denylist(hass: HomeAssistant, mock_client) -> None:
"""Test a denylist only config."""
handler_method = await _setup(
await _setup(
hass,
{
"exclude_domains": ["climate"],
@ -195,8 +175,8 @@ async def test_denylist(hass: HomeAssistant, mock_client) -> None:
]
for test in tests:
event = make_event(test.id)
handler_method(event)
hass.states.async_set(test.id, "not blank")
await hass.async_block_till_done()
was_called = publish_client.publish.call_count == 1
assert test.should_pass == was_called
@ -205,7 +185,7 @@ async def test_denylist(hass: HomeAssistant, mock_client) -> None:
async def test_filtered_allowlist(hass: HomeAssistant, mock_client) -> None:
"""Test an allowlist config with a filtering denylist."""
handler_method = await _setup(
await _setup(
hass,
{
"include_domains": ["light"],
@ -226,8 +206,8 @@ async def test_filtered_allowlist(hass: HomeAssistant, mock_client) -> None:
]
for test in tests:
event = make_event(test.id)
handler_method(event)
hass.states.async_set(test.id, "not blank")
await hass.async_block_till_done()
was_called = publish_client.publish.call_count == 1
assert test.should_pass == was_called
@ -236,7 +216,7 @@ async def test_filtered_allowlist(hass: HomeAssistant, mock_client) -> None:
async def test_filtered_denylist(hass: HomeAssistant, mock_client) -> None:
"""Test a denylist config with a filtering allowlist."""
handler_method = await _setup(
await _setup(
hass,
{
"include_entities": ["climate.included", "sensor.excluded_test"],
@ -257,8 +237,8 @@ async def test_filtered_denylist(hass: HomeAssistant, mock_client) -> None:
]
for test in tests:
event = make_event(test.id)
handler_method(event)
hass.states.async_set(test.id, "not blank")
await hass.async_block_till_done()
was_called = publish_client.publish.call_count == 1
assert test.should_pass == was_called

View File

@ -2,14 +2,13 @@
from dataclasses import dataclass
import datetime
from http import HTTPStatus
from unittest.mock import MagicMock, Mock, call, patch
from unittest.mock import ANY, MagicMock, Mock, call, patch
import pytest
import homeassistant.components.influxdb as influxdb
from homeassistant.components.influxdb.const import DEFAULT_BUCKET
from homeassistant.const import (
EVENT_STATE_CHANGED,
PERCENTAGE,
STATE_OFF,
STATE_ON,
@ -39,7 +38,6 @@ class FilterTest:
@pytest.fixture(autouse=True)
def mock_batch_timeout(hass, monkeypatch):
"""Mock the event bus listener and the batch timeout for tests."""
hass.bus.listen = MagicMock()
monkeypatch.setattr(
f"{INFLUX_PATH}.InfluxThread.batch_timeout",
Mock(return_value=0),
@ -129,8 +127,6 @@ async def test_setup_config_full(
assert await async_setup_component(hass, influxdb.DOMAIN, config)
await hass.async_block_till_done()
assert hass.bus.listen.called
assert hass.bus.listen.call_args_list[0][0][0] == EVENT_STATE_CHANGED
assert get_write_api(mock_client).call_count == 1
@ -263,8 +259,6 @@ async def test_setup_config_ssl(
assert await async_setup_component(hass, influxdb.DOMAIN, config)
await hass.async_block_till_done()
assert hass.bus.listen.called
assert hass.bus.listen.call_args_list[0][0][0] == EVENT_STATE_CHANGED
assert expected_client_args.items() <= mock_client.call_args.kwargs.items()
@ -285,8 +279,6 @@ async def test_setup_minimal_config(
assert await async_setup_component(hass, influxdb.DOMAIN, config)
await hass.async_block_till_done()
assert hass.bus.listen.called
assert hass.bus.listen.call_args_list[0][0][0] == EVENT_STATE_CHANGED
assert get_write_api(mock_client).call_count == 1
@ -347,7 +339,6 @@ async def _setup(hass, mock_influx_client, config_ext, get_write_api):
# A call is made to the write API during setup to test the connection.
# Therefore we reset the write API mock here before the test begins.
get_write_api(mock_influx_client).reset_mock()
return hass.bus.listen.call_args_list[0][0][1]
@pytest.mark.parametrize(
@ -372,7 +363,7 @@ async def test_event_listener(
hass: HomeAssistant, mock_client, config_ext, get_write_api, get_mock_call
) -> None:
"""Test the event listener."""
handler_method = await _setup(hass, mock_client, config_ext, get_write_api)
await _setup(hass, mock_client, config_ext, get_write_api)
# map of HA State to valid influxdb [state, value] fields
valid = {
@ -394,19 +385,11 @@ async def test_event_listener(
"updated_at": datetime.datetime(2017, 1, 1, 0, 0),
"multi_periods": "0.120.240.2023873",
}
state = MagicMock(
state=in_,
domain="fake",
entity_id="fake.entity-id",
object_id="entity",
attributes=attrs,
)
event = MagicMock(data={"new_state": state}, time_fired=12345)
body = [
{
"measurement": "foobars",
"tags": {"domain": "fake", "entity_id": "entity"},
"time": 12345,
"tags": {"domain": "fake", "entity_id": "entity_id"},
"time": ANY,
"fields": {
"longitude": 1.1,
"latitude": 2.2,
@ -427,7 +410,8 @@ async def test_event_listener(
if out[1] is not None:
body[0]["fields"]["value"] = out[1]
handler_method(event)
hass.states.async_set("fake.entity_id", in_, attrs)
await hass.async_block_till_done()
hass.data[influxdb.DOMAIN].block_till_done()
write_api = get_write_api(mock_client)
@ -458,30 +442,23 @@ async def test_event_listener_no_units(
hass: HomeAssistant, mock_client, config_ext, get_write_api, get_mock_call
) -> None:
"""Test the event listener for missing units."""
handler_method = await _setup(hass, mock_client, config_ext, get_write_api)
await _setup(hass, mock_client, config_ext, get_write_api)
for unit in (None, ""):
for unit in ("",):
if unit:
attrs = {"unit_of_measurement": unit}
else:
attrs = {}
state = MagicMock(
state=1,
domain="fake",
entity_id="fake.entity-id",
object_id="entity",
attributes=attrs,
)
event = MagicMock(data={"new_state": state}, time_fired=12345)
body = [
{
"measurement": "fake.entity-id",
"tags": {"domain": "fake", "entity_id": "entity"},
"time": 12345,
"measurement": "fake.entity_id",
"tags": {"domain": "fake", "entity_id": "entity_id"},
"time": ANY,
"fields": {"value": 1},
}
]
handler_method(event)
hass.states.async_set("fake.entity_id", 1, attrs)
await hass.async_block_till_done()
hass.data[influxdb.DOMAIN].block_till_done()
write_api = get_write_api(mock_client)
@ -512,26 +489,19 @@ async def test_event_listener_inf(
hass: HomeAssistant, mock_client, config_ext, get_write_api, get_mock_call
) -> None:
"""Test the event listener with large or invalid numbers."""
handler_method = await _setup(hass, mock_client, config_ext, get_write_api)
await _setup(hass, mock_client, config_ext, get_write_api)
attrs = {"bignumstring": "9" * 999, "nonumstring": "nan"}
state = MagicMock(
state=8,
domain="fake",
entity_id="fake.entity-id",
object_id="entity",
attributes=attrs,
)
event = MagicMock(data={"new_state": state}, time_fired=12345)
body = [
{
"measurement": "fake.entity-id",
"tags": {"domain": "fake", "entity_id": "entity"},
"time": 12345,
"measurement": "fake.entity_id",
"tags": {"domain": "fake", "entity_id": "entity_id"},
"time": ANY,
"fields": {"value": 8},
}
]
handler_method(event)
hass.states.async_set("fake.entity_id", 8, attrs)
await hass.async_block_till_done()
hass.data[influxdb.DOMAIN].block_till_done()
write_api = get_write_api(mock_client)
@ -561,26 +531,19 @@ async def test_event_listener_states(
hass: HomeAssistant, mock_client, config_ext, get_write_api, get_mock_call
) -> None:
"""Test the event listener against ignored states."""
handler_method = await _setup(hass, mock_client, config_ext, get_write_api)
await _setup(hass, mock_client, config_ext, get_write_api)
for state_state in (1, "unknown", "", "unavailable", None):
state = MagicMock(
state=state_state,
domain="fake",
entity_id="fake.entity-id",
object_id="entity",
attributes={},
)
event = MagicMock(data={"new_state": state}, time_fired=12345)
for state_state in (1, "unknown", "", "unavailable"):
body = [
{
"measurement": "fake.entity-id",
"tags": {"domain": "fake", "entity_id": "entity"},
"time": 12345,
"measurement": "fake.entity_id",
"tags": {"domain": "fake", "entity_id": "entity_id"},
"time": ANY,
"fields": {"value": 1},
}
]
handler_method(event)
hass.states.async_set("fake.entity_id", state_state)
await hass.async_block_till_done()
hass.data[influxdb.DOMAIN].block_till_done()
write_api = get_write_api(mock_client)
@ -592,27 +555,20 @@ async def test_event_listener_states(
write_api.reset_mock()
def execute_filter_test(hass, tests, handler_method, write_api, get_mock_call):
async def execute_filter_test(hass: HomeAssistant, tests, write_api, get_mock_call):
"""Execute all tests for a given filtering test."""
for test in tests:
domain, entity_id = split_entity_id(test.id)
state = MagicMock(
state=1,
domain=domain,
entity_id=test.id,
object_id=entity_id,
attributes={},
)
event = MagicMock(data={"new_state": state}, time_fired=12345)
body = [
{
"measurement": test.id,
"tags": {"domain": domain, "entity_id": entity_id},
"time": 12345,
"time": ANY,
"fields": {"value": 1},
}
]
handler_method(event)
hass.states.async_set(test.id, 1)
await hass.async_block_till_done()
hass.data[influxdb.DOMAIN].block_till_done()
if test.should_pass:
@ -647,14 +603,14 @@ async def test_event_listener_denylist(
"""Test the event listener against a denylist."""
config = {"exclude": {"entities": ["fake.denylisted"]}, "include": {}}
config.update(config_ext)
handler_method = await _setup(hass, mock_client, config, get_write_api)
await _setup(hass, mock_client, config, get_write_api)
write_api = get_write_api(mock_client)
tests = [
FilterTest("fake.ok", True),
FilterTest("fake.denylisted", False),
]
execute_filter_test(hass, tests, handler_method, write_api, get_mock_call)
await execute_filter_test(hass, tests, write_api, get_mock_call)
@pytest.mark.parametrize(
@ -681,14 +637,14 @@ async def test_event_listener_denylist_domain(
"""Test the event listener against a domain denylist."""
config = {"exclude": {"domains": ["another_fake"]}, "include": {}}
config.update(config_ext)
handler_method = await _setup(hass, mock_client, config, get_write_api)
await _setup(hass, mock_client, config, get_write_api)
write_api = get_write_api(mock_client)
tests = [
FilterTest("fake.ok", True),
FilterTest("another_fake.denylisted", False),
]
execute_filter_test(hass, tests, handler_method, write_api, get_mock_call)
await execute_filter_test(hass, tests, write_api, get_mock_call)
@pytest.mark.parametrize(
@ -715,14 +671,14 @@ async def test_event_listener_denylist_glob(
"""Test the event listener against a glob denylist."""
config = {"exclude": {"entity_globs": ["*.excluded_*"]}, "include": {}}
config.update(config_ext)
handler_method = await _setup(hass, mock_client, config, get_write_api)
await _setup(hass, mock_client, config, get_write_api)
write_api = get_write_api(mock_client)
tests = [
FilterTest("fake.ok", True),
FilterTest("fake.excluded_entity", False),
]
execute_filter_test(hass, tests, handler_method, write_api, get_mock_call)
await execute_filter_test(hass, tests, write_api, get_mock_call)
@pytest.mark.parametrize(
@ -749,14 +705,14 @@ async def test_event_listener_allowlist(
"""Test the event listener against an allowlist."""
config = {"include": {"entities": ["fake.included"]}, "exclude": {}}
config.update(config_ext)
handler_method = await _setup(hass, mock_client, config, get_write_api)
await _setup(hass, mock_client, config, get_write_api)
write_api = get_write_api(mock_client)
tests = [
FilterTest("fake.included", True),
FilterTest("fake.excluded", False),
]
execute_filter_test(hass, tests, handler_method, write_api, get_mock_call)
await execute_filter_test(hass, tests, write_api, get_mock_call)
@pytest.mark.parametrize(
@ -783,14 +739,14 @@ async def test_event_listener_allowlist_domain(
"""Test the event listener against a domain allowlist."""
config = {"include": {"domains": ["fake"]}, "exclude": {}}
config.update(config_ext)
handler_method = await _setup(hass, mock_client, config, get_write_api)
await _setup(hass, mock_client, config, get_write_api)
write_api = get_write_api(mock_client)
tests = [
FilterTest("fake.ok", True),
FilterTest("another_fake.excluded", False),
]
execute_filter_test(hass, tests, handler_method, write_api, get_mock_call)
await execute_filter_test(hass, tests, write_api, get_mock_call)
@pytest.mark.parametrize(
@ -817,14 +773,14 @@ async def test_event_listener_allowlist_glob(
"""Test the event listener against a glob allowlist."""
config = {"include": {"entity_globs": ["*.included_*"]}, "exclude": {}}
config.update(config_ext)
handler_method = await _setup(hass, mock_client, config, get_write_api)
await _setup(hass, mock_client, config, get_write_api)
write_api = get_write_api(mock_client)
tests = [
FilterTest("fake.included_entity", True),
FilterTest("fake.denied", False),
]
execute_filter_test(hass, tests, handler_method, write_api, get_mock_call)
await execute_filter_test(hass, tests, write_api, get_mock_call)
@pytest.mark.parametrize(
@ -862,7 +818,7 @@ async def test_event_listener_filtered_allowlist(
},
}
config.update(config_ext)
handler_method = await _setup(hass, mock_client, config, get_write_api)
await _setup(hass, mock_client, config, get_write_api)
write_api = get_write_api(mock_client)
tests = [
@ -874,7 +830,7 @@ async def test_event_listener_filtered_allowlist(
FilterTest("fake.excluded_entity", False),
FilterTest("another_fake.included_entity", True),
]
execute_filter_test(hass, tests, handler_method, write_api, get_mock_call)
await execute_filter_test(hass, tests, write_api, get_mock_call)
@pytest.mark.parametrize(
@ -904,7 +860,7 @@ async def test_event_listener_filtered_denylist(
"exclude": {"domains": ["another_fake"], "entity_globs": "*.excluded_*"},
}
config.update(config_ext)
handler_method = await _setup(hass, mock_client, config, get_write_api)
await _setup(hass, mock_client, config, get_write_api)
write_api = get_write_api(mock_client)
tests = [
@ -914,7 +870,7 @@ async def test_event_listener_filtered_denylist(
FilterTest("another_fake.denied", False),
FilterTest("fake.excluded_entity", False),
]
execute_filter_test(hass, tests, handler_method, write_api, get_mock_call)
await execute_filter_test(hass, tests, write_api, get_mock_call)
@pytest.mark.parametrize(
@ -939,7 +895,7 @@ async def test_event_listener_invalid_type(
hass: HomeAssistant, mock_client, config_ext, get_write_api, get_mock_call
) -> None:
"""Test the event listener when an attribute has an invalid type."""
handler_method = await _setup(hass, mock_client, config_ext, get_write_api)
await _setup(hass, mock_client, config_ext, get_write_api)
# map of HA State to valid influxdb [state, value] fields
valid = {
@ -957,19 +913,11 @@ async def test_event_listener_invalid_type(
"latitude": "2.2",
"invalid_attribute": ["value1", "value2"],
}
state = MagicMock(
state=in_,
domain="fake",
entity_id="fake.entity-id",
object_id="entity",
attributes=attrs,
)
event = MagicMock(data={"new_state": state}, time_fired=12345)
body = [
{
"measurement": "foobars",
"tags": {"domain": "fake", "entity_id": "entity"},
"time": 12345,
"tags": {"domain": "fake", "entity_id": "entity_id"},
"time": ANY,
"fields": {
"longitude": 1.1,
"latitude": 2.2,
@ -982,7 +930,8 @@ async def test_event_listener_invalid_type(
if out[1] is not None:
body[0]["fields"]["value"] = out[1]
handler_method(event)
hass.states.async_set("fake.entity_id", in_, attrs)
await hass.async_block_till_done()
hass.data[influxdb.DOMAIN].block_till_done()
write_api = get_write_api(mock_client)
@ -1015,25 +964,17 @@ async def test_event_listener_default_measurement(
"""Test the event listener with a default measurement."""
config = {"default_measurement": "state"}
config.update(config_ext)
handler_method = await _setup(hass, mock_client, config, get_write_api)
state = MagicMock(
state=1,
domain="fake",
entity_id="fake.ok",
object_id="ok",
attributes={},
)
event = MagicMock(data={"new_state": state}, time_fired=12345)
await _setup(hass, mock_client, config, get_write_api)
body = [
{
"measurement": "state",
"tags": {"domain": "fake", "entity_id": "ok"},
"time": 12345,
"time": ANY,
"fields": {"value": 1},
}
]
handler_method(event)
hass.states.async_set("fake.ok", 1)
await hass.async_block_till_done()
hass.data[influxdb.DOMAIN].block_till_done()
write_api = get_write_api(mock_client)
@ -1065,26 +1006,19 @@ async def test_event_listener_unit_of_measurement_field(
"""Test the event listener for unit of measurement field."""
config = {"override_measurement": "state"}
config.update(config_ext)
handler_method = await _setup(hass, mock_client, config, get_write_api)
await _setup(hass, mock_client, config, get_write_api)
attrs = {"unit_of_measurement": "foobars"}
state = MagicMock(
state="foo",
domain="fake",
entity_id="fake.entity-id",
object_id="entity",
attributes=attrs,
)
event = MagicMock(data={"new_state": state}, time_fired=12345)
body = [
{
"measurement": "state",
"tags": {"domain": "fake", "entity_id": "entity"},
"time": 12345,
"tags": {"domain": "fake", "entity_id": "entity_id"},
"time": ANY,
"fields": {"state": "foo", "unit_of_measurement_str": "foobars"},
}
]
handler_method(event)
hass.states.async_set("fake.entity_id", "foo", attrs)
await hass.async_block_till_done()
hass.data[influxdb.DOMAIN].block_till_done()
write_api = get_write_api(mock_client)
@ -1116,17 +1050,9 @@ async def test_event_listener_tags_attributes(
"""Test the event listener when some attributes should be tags."""
config = {"tags_attributes": ["friendly_fake"]}
config.update(config_ext)
handler_method = await _setup(hass, mock_client, config, get_write_api)
await _setup(hass, mock_client, config, get_write_api)
attrs = {"friendly_fake": "tag_str", "field_fake": "field_str"}
state = MagicMock(
state=1,
domain="fake",
entity_id="fake.something",
object_id="something",
attributes=attrs,
)
event = MagicMock(data={"new_state": state}, time_fired=12345)
body = [
{
"measurement": "fake.something",
@ -1135,11 +1061,12 @@ async def test_event_listener_tags_attributes(
"entity_id": "something",
"friendly_fake": "tag_str",
},
"time": 12345,
"time": ANY,
"fields": {"value": 1, "field_fake_str": "field_str"},
}
]
handler_method(event)
hass.states.async_set("fake.something", 1, attrs)
await hass.async_block_till_done()
hass.data[influxdb.DOMAIN].block_till_done()
write_api = get_write_api(mock_client)
@ -1179,7 +1106,7 @@ async def test_event_listener_component_override_measurement(
"component_config_domain": {"climate": {"override_measurement": "hvac"}},
}
config.update(config_ext)
handler_method = await _setup(hass, mock_client, config, get_write_api)
await _setup(hass, mock_client, config, get_write_api)
test_components = [
{"domain": "sensor", "id": "fake_humidity", "res": "humidity"},
@ -1188,23 +1115,16 @@ async def test_event_listener_component_override_measurement(
{"domain": "other", "id": "just_fake", "res": "other.just_fake"},
]
for comp in test_components:
state = MagicMock(
state=1,
domain=comp["domain"],
entity_id=f"{comp['domain']}.{comp['id']}",
object_id=comp["id"],
attributes={},
)
event = MagicMock(data={"new_state": state}, time_fired=12345)
body = [
{
"measurement": comp["res"],
"tags": {"domain": comp["domain"], "entity_id": comp["id"]},
"time": 12345,
"time": ANY,
"fields": {"value": 1},
}
]
handler_method(event)
hass.states.async_set(f"{comp['domain']}.{comp['id']}", 1)
await hass.async_block_till_done()
hass.data[influxdb.DOMAIN].block_till_done()
write_api = get_write_api(mock_client)
@ -1246,7 +1166,7 @@ async def test_event_listener_component_measurement_attr(
"component_config_domain": {"climate": {"override_measurement": "hvac"}},
}
config.update(config_ext)
handler_method = await _setup(hass, mock_client, config, get_write_api)
await _setup(hass, mock_client, config, get_write_api)
test_components = [
{
@ -1261,23 +1181,16 @@ async def test_event_listener_component_measurement_attr(
{"domain": "other", "id": "just_fake", "attrs": {}, "res": "other"},
]
for comp in test_components:
state = MagicMock(
state=1,
domain=comp["domain"],
entity_id=f"{comp['domain']}.{comp['id']}",
object_id=comp["id"],
attributes=comp["attrs"],
)
event = MagicMock(data={"new_state": state}, time_fired=12345)
body = [
{
"measurement": comp["res"],
"tags": {"domain": comp["domain"], "entity_id": comp["id"]},
"time": 12345,
"time": ANY,
"fields": {"value": 1},
}
]
handler_method(event)
hass.states.async_set(f"{comp['domain']}.{comp['id']}", 1, comp["attrs"])
await hass.async_block_till_done()
hass.data[influxdb.DOMAIN].block_till_done()
write_api = get_write_api(mock_client)
@ -1321,7 +1234,7 @@ async def test_event_listener_ignore_attributes(
},
}
config.update(config_ext)
handler_method = await _setup(hass, mock_client, config, get_write_api)
await _setup(hass, mock_client, config, get_write_api)
test_components = [
{
@ -1342,30 +1255,27 @@ async def test_event_listener_ignore_attributes(
]
for comp in test_components:
entity_id = f"{comp['domain']}.{comp['id']}"
state = MagicMock(
state=1,
domain=comp["domain"],
entity_id=entity_id,
object_id=comp["id"],
attributes={
"ignore": 1,
"id_ignore": 1,
"glob_ignore": 1,
"domain_ignore": 1,
},
)
event = MagicMock(data={"new_state": state}, time_fired=12345)
fields = {"value": 1}
fields.update(comp["attrs"])
body = [
{
"measurement": entity_id,
"tags": {"domain": comp["domain"], "entity_id": comp["id"]},
"time": 12345,
"time": ANY,
"fields": fields,
}
]
handler_method(event)
hass.states.async_set(
entity_id,
1,
{
"ignore": 1,
"id_ignore": 1,
"glob_ignore": 1,
"domain_ignore": 1,
},
)
await hass.async_block_till_done()
hass.data[influxdb.DOMAIN].block_till_done()
write_api = get_write_api(mock_client)
@ -1401,25 +1311,17 @@ async def test_event_listener_ignore_attributes_overlapping_entities(
"component_config_domain": {"sensor": {"ignore_attributes": ["ignore"]}},
}
config.update(config_ext)
handler_method = await _setup(hass, mock_client, config, get_write_api)
state = MagicMock(
state=1,
domain="sensor",
entity_id="sensor.fake",
object_id="fake",
attributes={"ignore": 1},
)
event = MagicMock(data={"new_state": state}, time_fired=12345)
await _setup(hass, mock_client, config, get_write_api)
body = [
{
"measurement": "units",
"tags": {"domain": "sensor", "entity_id": "fake"},
"time": 12345,
"time": ANY,
"fields": {"value": 1},
}
]
handler_method(event)
hass.states.async_set("sensor.fake", 1, {"ignore": 1})
await hass.async_block_till_done()
hass.data[influxdb.DOMAIN].block_till_done()
write_api = get_write_api(mock_client)
@ -1452,22 +1354,14 @@ async def test_event_listener_scheduled_write(
"""Test the event listener retries after a write failure."""
config = {"max_retries": 1}
config.update(config_ext)
handler_method = await _setup(hass, mock_client, config, get_write_api)
state = MagicMock(
state=1,
domain="fake",
entity_id="entity.id",
object_id="entity",
attributes={},
)
event = MagicMock(data={"new_state": state}, time_fired=12345)
await _setup(hass, mock_client, config, get_write_api)
write_api = get_write_api(mock_client)
write_api.side_effect = OSError("foo")
# Write fails
with patch.object(influxdb.time, "sleep") as mock_sleep:
handler_method(event)
hass.states.async_set("entity.entity_id", 1)
await hass.async_block_till_done()
hass.data[influxdb.DOMAIN].block_till_done()
assert mock_sleep.called
assert write_api.call_count == 2
@ -1475,7 +1369,8 @@ async def test_event_listener_scheduled_write(
# Write works again
write_api.side_effect = None
with patch.object(influxdb.time, "sleep") as mock_sleep:
handler_method(event)
hass.states.async_set("entity.entity_id", "2")
await hass.async_block_till_done()
hass.data[influxdb.DOMAIN].block_till_done()
assert not mock_sleep.called
assert write_api.call_count == 3
@ -1503,16 +1398,7 @@ async def test_event_listener_backlog_full(
hass: HomeAssistant, mock_client, config_ext, get_write_api, get_mock_call
) -> None:
"""Test the event listener drops old events when backlog gets full."""
handler_method = await _setup(hass, mock_client, config_ext, get_write_api)
state = MagicMock(
state=1,
domain="fake",
entity_id="entity.id",
object_id="entity",
attributes={},
)
event = MagicMock(data={"new_state": state}, time_fired=12345)
await _setup(hass, mock_client, config_ext, get_write_api)
monotonic_time = 0
@ -1523,7 +1409,8 @@ async def test_event_listener_backlog_full(
return monotonic_time
with patch("homeassistant.components.influxdb.time.monotonic", new=fast_monotonic):
handler_method(event)
hass.states.async_set("entity.id", 1)
await hass.async_block_till_done()
hass.data[influxdb.DOMAIN].block_till_done()
assert get_write_api(mock_client).call_count == 0
@ -1551,26 +1438,17 @@ async def test_event_listener_attribute_name_conflict(
hass: HomeAssistant, mock_client, config_ext, get_write_api, get_mock_call
) -> None:
"""Test the event listener when an attribute conflicts with another field."""
handler_method = await _setup(hass, mock_client, config_ext, get_write_api)
attrs = {"value": "value_str"}
state = MagicMock(
state=1,
domain="fake",
entity_id="fake.something",
object_id="something",
attributes=attrs,
)
event = MagicMock(data={"new_state": state}, time_fired=12345)
await _setup(hass, mock_client, config_ext, get_write_api)
body = [
{
"measurement": "fake.something",
"tags": {"domain": "fake", "entity_id": "something"},
"time": 12345,
"time": ANY,
"fields": {"value": 1, "value__str": "value_str"},
}
]
handler_method(event)
hass.states.async_set("fake.something", 1, {"value": "value_str"})
await hass.async_block_till_done()
hass.data[influxdb.DOMAIN].block_till_done()
write_api = get_write_api(mock_client)
@ -1642,7 +1520,6 @@ async def test_connection_failure_on_startup(
== 1
)
event_helper.call_later.assert_called_once()
hass.bus.listen.assert_not_called()
@pytest.mark.parametrize(
@ -1686,21 +1563,14 @@ async def test_invalid_inputs_error(
But Influx is an external service so there may be edge cases that
haven't been encountered yet.
"""
handler_method = await _setup(hass, mock_client, config_ext, get_write_api)
await _setup(hass, mock_client, config_ext, get_write_api)
write_api = get_write_api(mock_client)
write_api.side_effect = test_exception
state = MagicMock(
state=1,
domain="fake",
entity_id="fake.something",
object_id="something",
attributes={},
)
event = MagicMock(data={"new_state": state}, time_fired=12345)
with patch(f"{INFLUX_PATH}.time.sleep") as sleep:
handler_method(event)
hass.states.async_set("fake.something", 1)
await hass.async_block_till_done()
hass.data[influxdb.DOMAIN].block_till_done()
write_api.assert_called_once()
@ -1786,29 +1656,25 @@ async def test_precision(
"precision": precision,
}
config.update(config_ext)
handler_method = await _setup(hass, mock_client, config, get_write_api)
await _setup(hass, mock_client, config, get_write_api)
value = "1.9"
attrs = {
"unit_of_measurement": "foobars",
}
state = MagicMock(
state=value,
domain="fake",
entity_id="fake.entity-id",
object_id="entity",
attributes=attrs,
)
event = MagicMock(data={"new_state": state}, time_fired=12345)
body = [
{
"measurement": "foobars",
"tags": {"domain": "fake", "entity_id": "entity"},
"time": 12345,
"tags": {"domain": "fake", "entity_id": "entity_id"},
"time": ANY,
"fields": {"value": float(value)},
}
]
handler_method(event)
hass.states.async_set(
"fake.entity_id",
value,
{
"unit_of_measurement": "foobars",
},
)
await hass.async_block_till_done()
hass.data[influxdb.DOMAIN].block_till_done()
write_api = get_write_api(mock_client)

View File

@ -1,10 +1,10 @@
"""The tests for the Logentries component."""
from unittest.mock import MagicMock, call, patch
from unittest.mock import ANY, call, patch
import pytest
import homeassistant.components.logentries as logentries
from homeassistant.const import EVENT_STATE_CHANGED, STATE_OFF, STATE_ON
from homeassistant.const import STATE_OFF, STATE_ON
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
@ -12,19 +12,23 @@ from homeassistant.setup import async_setup_component
async def test_setup_config_full(hass: HomeAssistant) -> None:
"""Test setup with all data."""
config = {"logentries": {"token": "secret"}}
hass.bus.listen = MagicMock()
assert await async_setup_component(hass, logentries.DOMAIN, config)
assert hass.bus.listen.called
assert hass.bus.listen.call_args_list[0][0][0] == EVENT_STATE_CHANGED
with patch("homeassistant.components.logentries.requests.post") as mock_post:
hass.states.async_set("fake.entity", STATE_ON)
await hass.async_block_till_done()
assert len(mock_post.mock_calls) == 1
async def test_setup_config_defaults(hass: HomeAssistant) -> None:
"""Test setup with defaults."""
config = {"logentries": {"token": "token"}}
hass.bus.listen = MagicMock()
assert await async_setup_component(hass, logentries.DOMAIN, config)
assert hass.bus.listen.called
assert hass.bus.listen.call_args_list[0][0][0] == EVENT_STATE_CHANGED
with patch("homeassistant.components.logentries.requests.post") as mock_post:
hass.states.async_set("fake.entity", STATE_ON)
await hass.async_block_till_done()
assert len(mock_post.mock_calls) == 1
@pytest.fixture
@ -47,28 +51,24 @@ async def test_event_listener(hass: HomeAssistant, mock_dump, mock_requests) ->
mock_post = mock_requests.post
mock_requests.exceptions.RequestException = Exception
config = {"logentries": {"token": "token"}}
hass.bus.listen = MagicMock()
assert await async_setup_component(hass, logentries.DOMAIN, config)
handler_method = hass.bus.listen.call_args_list[0][0][1]
valid = {"1": 1, "1.0": 1.0, STATE_ON: 1, STATE_OFF: 0, "foo": "foo"}
for in_, out in valid.items():
state = MagicMock(state=in_, domain="fake", object_id="entity", attributes={})
event = MagicMock(data={"new_state": state}, time_fired=12345)
body = [
{
"domain": "fake",
"entity_id": "entity",
"attributes": {},
"time": "12345",
"value": out,
}
]
payload = {
"host": "https://webhook.logentries.com/noformat/logs/token",
"event": body,
"event": [
{
"domain": "fake",
"entity_id": "entity",
"attributes": {},
"time": ANY,
"value": out,
}
],
}
handler_method(event)
hass.states.async_set("fake.entity", in_)
await hass.async_block_till_done()
assert mock_post.call_count == 1
assert mock_post.call_args == call(payload["host"], data=payload, timeout=10)
mock_post.reset_mock()

View File

@ -44,7 +44,6 @@ from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONTENT_TYPE_TEXT_PLAIN,
DEGREE,
EVENT_STATE_CHANGED,
PERCENTAGE,
STATE_CLOSED,
STATE_CLOSING,
@ -59,7 +58,7 @@ from homeassistant.const import (
UnitOfEnergy,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant, split_entity_id
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.setup import async_setup_component
from homeassistant.util import dt as dt_util
@ -1568,23 +1567,13 @@ def mock_client_fixture():
yield counter_client
@pytest.fixture
def mock_bus(hass):
"""Mock the event bus listener."""
hass.bus.listen = mock.MagicMock()
@pytest.mark.usefixtures("mock_bus")
async def test_minimal_config(hass: HomeAssistant, mock_client) -> None:
"""Test the minimal config and defaults of component."""
config = {prometheus.DOMAIN: {}}
assert await async_setup_component(hass, prometheus.DOMAIN, config)
await hass.async_block_till_done()
assert hass.bus.listen.called
assert hass.bus.listen.call_args_list[0][0][0] == EVENT_STATE_CHANGED
@pytest.mark.usefixtures("mock_bus")
async def test_full_config(hass: HomeAssistant, mock_client) -> None:
"""Test the full config of component."""
config = {
@ -1607,21 +1596,6 @@ async def test_full_config(hass: HomeAssistant, mock_client) -> None:
}
assert await async_setup_component(hass, prometheus.DOMAIN, config)
await hass.async_block_till_done()
assert hass.bus.listen.called
assert hass.bus.listen.call_args_list[0][0][0] == EVENT_STATE_CHANGED
def make_event(entity_id):
"""Make a mock event for test."""
domain = split_entity_id(entity_id)[0]
state = mock.MagicMock(
state="not blank",
domain=domain,
entity_id=entity_id,
object_id="entity",
attributes={},
)
return mock.MagicMock(data={"new_state": state}, time_fired=12345)
async def _setup(hass, filter_config):
@ -1629,13 +1603,11 @@ async def _setup(hass, filter_config):
config = {prometheus.DOMAIN: {"filter": filter_config}}
assert await async_setup_component(hass, prometheus.DOMAIN, config)
await hass.async_block_till_done()
return hass.bus.listen.call_args_list[0][0][1]
@pytest.mark.usefixtures("mock_bus")
async def test_allowlist(hass: HomeAssistant, mock_client) -> None:
"""Test an allowlist only config."""
handler_method = await _setup(
await _setup(
hass,
{
"include_domains": ["fake"],
@ -1654,18 +1626,17 @@ async def test_allowlist(hass: HomeAssistant, mock_client) -> None:
]
for test in tests:
event = make_event(test.id)
handler_method(event)
hass.states.async_set(test.id, "not blank")
await hass.async_block_till_done()
was_called = mock_client.labels.call_count == 1
assert test.should_pass == was_called
mock_client.labels.reset_mock()
@pytest.mark.usefixtures("mock_bus")
async def test_denylist(hass: HomeAssistant, mock_client) -> None:
"""Test a denylist only config."""
handler_method = await _setup(
await _setup(
hass,
{
"exclude_domains": ["fake"],
@ -1684,18 +1655,17 @@ async def test_denylist(hass: HomeAssistant, mock_client) -> None:
]
for test in tests:
event = make_event(test.id)
handler_method(event)
hass.states.async_set(test.id, "not blank")
await hass.async_block_till_done()
was_called = mock_client.labels.call_count == 1
assert test.should_pass == was_called
mock_client.labels.reset_mock()
@pytest.mark.usefixtures("mock_bus")
async def test_filtered_denylist(hass: HomeAssistant, mock_client) -> None:
"""Test a denylist config with a filtering allowlist."""
handler_method = await _setup(
await _setup(
hass,
{
"include_entities": ["fake.included", "test.excluded_test"],
@ -1715,8 +1685,8 @@ async def test_filtered_denylist(hass: HomeAssistant, mock_client) -> None:
]
for test in tests:
event = make_event(test.id)
handler_method(event)
hass.states.async_set(test.id, "not blank")
await hass.async_block_till_done()
was_called = mock_client.labels.call_count == 1
assert test.should_pass == was_called

View File

@ -1,13 +1,12 @@
"""The tests for the StatsD feeder."""
from unittest import mock
from unittest.mock import MagicMock, patch
from unittest.mock import patch
import pytest
import voluptuous as vol
import homeassistant.components.statsd as statsd
from homeassistant.const import EVENT_STATE_CHANGED, STATE_OFF, STATE_ON
import homeassistant.core as ha
from homeassistant.const import STATE_OFF, STATE_ON
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
@ -32,15 +31,15 @@ def test_invalid_config() -> None:
async def test_statsd_setup_full(hass: HomeAssistant) -> None:
"""Test setup with all data."""
config = {"statsd": {"host": "host", "port": 123, "rate": 1, "prefix": "foo"}}
hass.bus.listen = MagicMock()
with patch("statsd.StatsClient") as mock_init:
assert await async_setup_component(hass, statsd.DOMAIN, config)
assert mock_init.call_count == 1
assert mock_init.call_args == mock.call(host="host", port=123, prefix="foo")
assert hass.bus.listen.called
assert hass.bus.listen.call_args_list[0][0][0] == EVENT_STATE_CHANGED
hass.states.async_set("domain.test", "on")
await hass.async_block_till_done()
assert len(mock_init.mock_calls) == 3
async def test_statsd_setup_defaults(hass: HomeAssistant) -> None:
@ -50,13 +49,14 @@ async def test_statsd_setup_defaults(hass: HomeAssistant) -> None:
config["statsd"][statsd.CONF_PORT] = statsd.DEFAULT_PORT
config["statsd"][statsd.CONF_PREFIX] = statsd.DEFAULT_PREFIX
hass.bus.listen = MagicMock()
with patch("statsd.StatsClient") as mock_init:
assert await async_setup_component(hass, statsd.DOMAIN, config)
assert mock_init.call_count == 1
assert mock_init.call_args == mock.call(host="host", port=8125, prefix="hass")
assert hass.bus.listen.called
hass.states.async_set("domain.test", "on")
await hass.async_block_till_done()
assert len(mock_init.mock_calls) == 3
async def test_event_listener_defaults(hass: HomeAssistant, mock_client) -> None:
@ -65,31 +65,27 @@ async def test_event_listener_defaults(hass: HomeAssistant, mock_client) -> None
config["statsd"][statsd.CONF_RATE] = statsd.DEFAULT_RATE
hass.bus.listen = MagicMock()
await async_setup_component(hass, statsd.DOMAIN, config)
assert hass.bus.listen.called
handler_method = hass.bus.listen.call_args_list[0][0][1]
valid = {"1": 1, "1.0": 1.0, "custom": 3, STATE_ON: 1, STATE_OFF: 0}
for in_, out in valid.items():
state = MagicMock(state=in_, attributes={"attribute key": 3.2})
handler_method(MagicMock(data={"new_state": state}))
hass.states.async_set("domain.test", in_, {"attribute key": 3.2})
await hass.async_block_till_done()
mock_client.gauge.assert_has_calls(
[mock.call(state.entity_id, out, statsd.DEFAULT_RATE)]
[mock.call("domain.test", out, statsd.DEFAULT_RATE)]
)
mock_client.gauge.reset_mock()
assert mock_client.incr.call_count == 1
assert mock_client.incr.call_args == mock.call(
state.entity_id, rate=statsd.DEFAULT_RATE
"domain.test", rate=statsd.DEFAULT_RATE
)
mock_client.incr.reset_mock()
for invalid in ("foo", "", object):
handler_method(
MagicMock(data={"new_state": ha.State("domain.test", invalid, {})})
)
hass.states.async_set("domain.test", invalid, {})
await hass.async_block_till_done()
assert not mock_client.gauge.called
assert mock_client.incr.called
@ -100,19 +96,16 @@ async def test_event_listener_attr_details(hass: HomeAssistant, mock_client) ->
config["statsd"][statsd.CONF_RATE] = statsd.DEFAULT_RATE
hass.bus.listen = MagicMock()
await async_setup_component(hass, statsd.DOMAIN, config)
assert hass.bus.listen.called
handler_method = hass.bus.listen.call_args_list[0][0][1]
valid = {"1": 1, "1.0": 1.0, STATE_ON: 1, STATE_OFF: 0}
for in_, out in valid.items():
state = MagicMock(state=in_, attributes={"attribute key": 3.2})
handler_method(MagicMock(data={"new_state": state}))
hass.states.async_set("domain.test", in_, {"attribute key": 3.2})
await hass.async_block_till_done()
mock_client.gauge.assert_has_calls(
[
mock.call(f"{state.entity_id}.state", out, statsd.DEFAULT_RATE),
mock.call(f"{state.entity_id}.attribute_key", 3.2, statsd.DEFAULT_RATE),
mock.call("domain.test.state", out, statsd.DEFAULT_RATE),
mock.call("domain.test.attribute_key", 3.2, statsd.DEFAULT_RATE),
]
)
@ -120,13 +113,12 @@ async def test_event_listener_attr_details(hass: HomeAssistant, mock_client) ->
assert mock_client.incr.call_count == 1
assert mock_client.incr.call_args == mock.call(
state.entity_id, rate=statsd.DEFAULT_RATE
"domain.test", rate=statsd.DEFAULT_RATE
)
mock_client.incr.reset_mock()
for invalid in ("foo", "", object):
handler_method(
MagicMock(data={"new_state": ha.State("domain.test", invalid, {})})
)
hass.states.async_set("domain.test", invalid, {})
await hass.async_block_till_done()
assert not mock_client.gauge.called
assert mock_client.incr.called