Keep task references while running (#87970)
* Keep task references while running * Update pilight tests pointing at correct logger call * Fix graphite tests * Fix profiler tests * More graphite test fixes * Remove extra sleep * Fix tests * Shutdown background tasks as part of stage 1 * Remove unnecessary sleep in test * Remove unused method on mock hass * Skip on cancelled too * Remove background tasks * Test trigger variables without actually sleeping * Fix graphite * One more graphite grrrrrrr
This commit is contained in:
parent
e41af8928b
commit
d54f59478f
12 changed files with 97 additions and 210 deletions
|
@ -69,7 +69,7 @@ def setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||
else:
|
||||
_LOGGER.debug("No connection check for UDP possible")
|
||||
|
||||
GraphiteFeeder(hass, host, port, protocol, prefix)
|
||||
hass.data[DOMAIN] = GraphiteFeeder(hass, host, port, protocol, prefix)
|
||||
return True
|
||||
|
||||
|
||||
|
|
|
@ -278,8 +278,7 @@ class HomeAssistant:
|
|||
def __init__(self) -> None:
|
||||
"""Initialize new Home Assistant object."""
|
||||
self.loop = asyncio.get_running_loop()
|
||||
self._pending_tasks: list[asyncio.Future[Any]] = []
|
||||
self._track_task = True
|
||||
self._tasks: set[asyncio.Future[Any]] = set()
|
||||
self.bus = EventBus(self)
|
||||
self.services = ServiceRegistry(self)
|
||||
self.states = StateMachine(self.bus, self.loop)
|
||||
|
@ -355,12 +354,14 @@ class HomeAssistant:
|
|||
self.bus.async_fire(EVENT_CORE_CONFIG_UPDATE)
|
||||
self.bus.async_fire(EVENT_HOMEASSISTANT_START)
|
||||
|
||||
try:
|
||||
# Only block for EVENT_HOMEASSISTANT_START listener
|
||||
self.async_stop_track_tasks()
|
||||
async with self.timeout.async_timeout(TIMEOUT_EVENT_START):
|
||||
await self.async_block_till_done()
|
||||
except asyncio.TimeoutError:
|
||||
if not self._tasks:
|
||||
pending: set[asyncio.Future[Any]] | None = None
|
||||
else:
|
||||
_done, pending = await asyncio.wait(
|
||||
self._tasks, timeout=TIMEOUT_EVENT_START
|
||||
)
|
||||
|
||||
if pending:
|
||||
_LOGGER.warning(
|
||||
(
|
||||
"Something is blocking Home Assistant from wrapping up the start up"
|
||||
|
@ -496,9 +497,8 @@ class HomeAssistant:
|
|||
hassjob.target = cast(Callable[..., _R], hassjob.target)
|
||||
task = self.loop.run_in_executor(None, hassjob.target, *args)
|
||||
|
||||
# If a task is scheduled
|
||||
if self._track_task:
|
||||
self._pending_tasks.append(task)
|
||||
self._tasks.add(task)
|
||||
task.add_done_callback(self._tasks.remove)
|
||||
|
||||
return task
|
||||
|
||||
|
@ -518,9 +518,8 @@ class HomeAssistant:
|
|||
target: target to call.
|
||||
"""
|
||||
task = self.loop.create_task(target)
|
||||
|
||||
if self._track_task:
|
||||
self._pending_tasks.append(task)
|
||||
self._tasks.add(task)
|
||||
task.add_done_callback(self._tasks.remove)
|
||||
|
||||
return task
|
||||
|
||||
|
@ -530,23 +529,11 @@ class HomeAssistant:
|
|||
) -> asyncio.Future[_T]:
|
||||
"""Add an executor job from within the event loop."""
|
||||
task = self.loop.run_in_executor(None, target, *args)
|
||||
|
||||
# If a task is scheduled
|
||||
if self._track_task:
|
||||
self._pending_tasks.append(task)
|
||||
self._tasks.add(task)
|
||||
task.add_done_callback(self._tasks.remove)
|
||||
|
||||
return task
|
||||
|
||||
@callback
|
||||
def async_track_tasks(self) -> None:
|
||||
"""Track tasks so you can wait for all tasks to be done."""
|
||||
self._track_task = True
|
||||
|
||||
@callback
|
||||
def async_stop_track_tasks(self) -> None:
|
||||
"""Stop track tasks so you can't wait for all tasks to be done."""
|
||||
self._track_task = False
|
||||
|
||||
@overload
|
||||
@callback
|
||||
def async_run_hass_job(
|
||||
|
@ -640,29 +627,25 @@ class HomeAssistant:
|
|||
# To flush out any call_soon_threadsafe
|
||||
await asyncio.sleep(0)
|
||||
start_time: float | None = None
|
||||
current_task = asyncio.current_task()
|
||||
|
||||
while self._pending_tasks:
|
||||
pending = [task for task in self._pending_tasks if not task.done()]
|
||||
self._pending_tasks.clear()
|
||||
if pending:
|
||||
await self._await_and_log_pending(pending)
|
||||
while tasks := [task for task in self._tasks if task is not current_task]:
|
||||
await self._await_and_log_pending(tasks)
|
||||
|
||||
if start_time is None:
|
||||
# Avoid calling monotonic() until we know
|
||||
# we may need to start logging blocked tasks.
|
||||
start_time = 0
|
||||
elif start_time == 0:
|
||||
# If we have waited twice then we set the start
|
||||
# time
|
||||
start_time = monotonic()
|
||||
elif monotonic() - start_time > BLOCK_LOG_TIMEOUT:
|
||||
# We have waited at least three loops and new tasks
|
||||
# continue to block. At this point we start
|
||||
# logging all waiting tasks.
|
||||
for task in pending:
|
||||
_LOGGER.debug("Waiting for task: %s", task)
|
||||
else:
|
||||
await asyncio.sleep(0)
|
||||
if start_time is None:
|
||||
# Avoid calling monotonic() until we know
|
||||
# we may need to start logging blocked tasks.
|
||||
start_time = 0
|
||||
elif start_time == 0:
|
||||
# If we have waited twice then we set the start
|
||||
# time
|
||||
start_time = monotonic()
|
||||
elif monotonic() - start_time > BLOCK_LOG_TIMEOUT:
|
||||
# We have waited at least three loops and new tasks
|
||||
# continue to block. At this point we start
|
||||
# logging all waiting tasks.
|
||||
for task in tasks:
|
||||
_LOGGER.debug("Waiting for task: %s", task)
|
||||
|
||||
async def _await_and_log_pending(self, pending: Collection[Awaitable[Any]]) -> None:
|
||||
"""Await and log tasks that take a long time."""
|
||||
|
@ -706,7 +689,6 @@ class HomeAssistant:
|
|||
|
||||
# stage 1
|
||||
self.state = CoreState.stopping
|
||||
self.async_track_tasks()
|
||||
self.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
|
||||
try:
|
||||
async with self.timeout.async_timeout(STAGE_1_SHUTDOWN_TIMEOUT):
|
||||
|
|
|
@ -3,14 +3,7 @@ from __future__ import annotations
|
|||
|
||||
import asyncio
|
||||
from collections import OrderedDict
|
||||
from collections.abc import (
|
||||
Awaitable,
|
||||
Callable,
|
||||
Collection,
|
||||
Generator,
|
||||
Mapping,
|
||||
Sequence,
|
||||
)
|
||||
from collections.abc import Awaitable, Callable, Generator, Mapping, Sequence
|
||||
from contextlib import contextmanager
|
||||
from datetime import datetime, timedelta, timezone
|
||||
import functools as ft
|
||||
|
@ -22,8 +15,6 @@ import os
|
|||
import pathlib
|
||||
import threading
|
||||
import time
|
||||
from time import monotonic
|
||||
import types
|
||||
from typing import Any, NoReturn
|
||||
from unittest.mock import AsyncMock, Mock, patch
|
||||
|
||||
|
@ -51,7 +42,6 @@ from homeassistant.const import (
|
|||
STATE_ON,
|
||||
)
|
||||
from homeassistant.core import (
|
||||
BLOCK_LOG_TIMEOUT,
|
||||
CoreState,
|
||||
Event,
|
||||
HomeAssistant,
|
||||
|
@ -221,76 +211,9 @@ async def async_test_home_assistant(event_loop, load_registries=True):
|
|||
|
||||
return orig_async_create_task(coroutine)
|
||||
|
||||
async def async_wait_for_task_count(self, max_remaining_tasks: int = 0) -> None:
|
||||
"""Block until at most max_remaining_tasks remain.
|
||||
|
||||
Based on HomeAssistant.async_block_till_done
|
||||
"""
|
||||
# To flush out any call_soon_threadsafe
|
||||
await asyncio.sleep(0)
|
||||
start_time: float | None = None
|
||||
|
||||
while len(self._pending_tasks) > max_remaining_tasks:
|
||||
pending: Collection[Awaitable[Any]] = [
|
||||
task for task in self._pending_tasks if not task.done()
|
||||
]
|
||||
self._pending_tasks.clear()
|
||||
if len(pending) > max_remaining_tasks:
|
||||
remaining_pending = await self._await_count_and_log_pending(
|
||||
pending, max_remaining_tasks=max_remaining_tasks
|
||||
)
|
||||
self._pending_tasks.extend(remaining_pending)
|
||||
|
||||
if start_time is None:
|
||||
# Avoid calling monotonic() until we know
|
||||
# we may need to start logging blocked tasks.
|
||||
start_time = 0
|
||||
elif start_time == 0:
|
||||
# If we have waited twice then we set the start
|
||||
# time
|
||||
start_time = monotonic()
|
||||
elif monotonic() - start_time > BLOCK_LOG_TIMEOUT:
|
||||
# We have waited at least three loops and new tasks
|
||||
# continue to block. At this point we start
|
||||
# logging all waiting tasks.
|
||||
for task in pending:
|
||||
_LOGGER.debug("Waiting for task: %s", task)
|
||||
else:
|
||||
self._pending_tasks.extend(pending)
|
||||
await asyncio.sleep(0)
|
||||
|
||||
async def _await_count_and_log_pending(
|
||||
self, pending: Collection[Awaitable[Any]], max_remaining_tasks: int = 0
|
||||
) -> Collection[Awaitable[Any]]:
|
||||
"""Block at most max_remaining_tasks remain and log tasks that take a long time.
|
||||
|
||||
Based on HomeAssistant._await_and_log_pending
|
||||
"""
|
||||
wait_time = 0
|
||||
|
||||
return_when = asyncio.ALL_COMPLETED
|
||||
if max_remaining_tasks:
|
||||
return_when = asyncio.FIRST_COMPLETED
|
||||
|
||||
while len(pending) > max_remaining_tasks:
|
||||
_, pending = await asyncio.wait(
|
||||
pending, timeout=BLOCK_LOG_TIMEOUT, return_when=return_when
|
||||
)
|
||||
if not pending or max_remaining_tasks:
|
||||
return pending
|
||||
wait_time += BLOCK_LOG_TIMEOUT
|
||||
for task in pending:
|
||||
_LOGGER.debug("Waited %s seconds for task: %s", wait_time, task)
|
||||
|
||||
return []
|
||||
|
||||
hass.async_add_job = async_add_job
|
||||
hass.async_add_executor_job = async_add_executor_job
|
||||
hass.async_create_task = async_create_task
|
||||
hass.async_wait_for_task_count = types.MethodType(async_wait_for_task_count, hass)
|
||||
hass._await_count_and_log_pending = types.MethodType(
|
||||
_await_count_and_log_pending, hass
|
||||
)
|
||||
|
||||
hass.data[loader.DATA_CUSTOM_COMPONENTS] = {}
|
||||
|
||||
|
@ -328,17 +251,6 @@ async def async_test_home_assistant(event_loop, load_registries=True):
|
|||
|
||||
hass.state = CoreState.running
|
||||
|
||||
# Mock async_start
|
||||
orig_start = hass.async_start
|
||||
|
||||
async def mock_async_start():
|
||||
"""Start the mocking."""
|
||||
# We only mock time during tests and we want to track tasks
|
||||
with patch.object(hass, "async_stop_track_tasks"):
|
||||
await orig_start()
|
||||
|
||||
hass.async_start = mock_async_start
|
||||
|
||||
@callback
|
||||
def clear_instance(event):
|
||||
"""Clear global instance."""
|
||||
|
|
|
@ -239,5 +239,6 @@ async def test_initialize_start(hass: HomeAssistant) -> None:
|
|||
) as mock_activate:
|
||||
hass.bus.fire(EVENT_HOMEASSISTANT_START)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(mock_activate.mock_calls) == 1
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
"""The tests for the Graphite component."""
|
||||
import asyncio
|
||||
import socket
|
||||
from unittest import mock
|
||||
from unittest.mock import patch
|
||||
|
@ -91,9 +90,11 @@ async def test_start(hass: HomeAssistant, mock_socket, mock_time) -> None:
|
|||
mock_socket.reset_mock()
|
||||
|
||||
await hass.async_start()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
hass.states.async_set("test.entity", STATE_ON)
|
||||
await asyncio.sleep(0.1)
|
||||
await hass.async_block_till_done()
|
||||
hass.data[graphite.DOMAIN]._queue.join()
|
||||
|
||||
assert mock_socket.return_value.connect.call_count == 1
|
||||
assert mock_socket.return_value.connect.call_args == mock.call(("localhost", 2003))
|
||||
|
@ -114,9 +115,11 @@ async def test_shutdown(hass: HomeAssistant, mock_socket, mock_time) -> None:
|
|||
mock_socket.reset_mock()
|
||||
|
||||
await hass.async_start()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
hass.states.async_set("test.entity", STATE_ON)
|
||||
await asyncio.sleep(0.1)
|
||||
await hass.async_block_till_done()
|
||||
hass.data[graphite.DOMAIN]._queue.join()
|
||||
|
||||
assert mock_socket.return_value.connect.call_count == 1
|
||||
assert mock_socket.return_value.connect.call_args == mock.call(("localhost", 2003))
|
||||
|
@ -134,7 +137,7 @@ async def test_shutdown(hass: HomeAssistant, mock_socket, mock_time) -> None:
|
|||
await hass.async_block_till_done()
|
||||
|
||||
hass.states.async_set("test.entity", STATE_OFF)
|
||||
await asyncio.sleep(0.1)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_socket.return_value.connect.call_count == 0
|
||||
assert mock_socket.return_value.sendall.call_count == 0
|
||||
|
@ -156,9 +159,11 @@ async def test_report_attributes(hass: HomeAssistant, mock_socket, mock_time) ->
|
|||
mock_socket.reset_mock()
|
||||
|
||||
await hass.async_start()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
hass.states.async_set("test.entity", STATE_ON, attrs)
|
||||
await asyncio.sleep(0.1)
|
||||
await hass.async_block_till_done()
|
||||
hass.data[graphite.DOMAIN]._queue.join()
|
||||
|
||||
assert mock_socket.return_value.connect.call_count == 1
|
||||
assert mock_socket.return_value.connect.call_args == mock.call(("localhost", 2003))
|
||||
|
@ -186,9 +191,11 @@ async def test_report_with_string_state(
|
|||
mock_socket.reset_mock()
|
||||
|
||||
await hass.async_start()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
hass.states.async_set("test.entity", "above_horizon", {"foo": 1.0})
|
||||
await asyncio.sleep(0.1)
|
||||
await hass.async_block_till_done()
|
||||
hass.data[graphite.DOMAIN]._queue.join()
|
||||
|
||||
assert mock_socket.return_value.connect.call_count == 1
|
||||
assert mock_socket.return_value.connect.call_args == mock.call(("localhost", 2003))
|
||||
|
@ -203,7 +210,8 @@ async def test_report_with_string_state(
|
|||
mock_socket.reset_mock()
|
||||
|
||||
hass.states.async_set("test.entity", "not_float")
|
||||
await asyncio.sleep(0.1)
|
||||
await hass.async_block_till_done()
|
||||
hass.data[graphite.DOMAIN]._queue.join()
|
||||
|
||||
assert mock_socket.return_value.connect.call_count == 0
|
||||
assert mock_socket.return_value.sendall.call_count == 0
|
||||
|
@ -221,13 +229,15 @@ async def test_report_with_binary_state(
|
|||
mock_socket.reset_mock()
|
||||
|
||||
await hass.async_start()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
expected = [
|
||||
"ha.test.entity.foo 1.000000 12345",
|
||||
"ha.test.entity.state 1.000000 12345",
|
||||
]
|
||||
hass.states.async_set("test.entity", STATE_ON, {"foo": 1.0})
|
||||
await asyncio.sleep(0.1)
|
||||
await hass.async_block_till_done()
|
||||
hass.data[graphite.DOMAIN]._queue.join()
|
||||
|
||||
assert mock_socket.return_value.connect.call_count == 1
|
||||
assert mock_socket.return_value.connect.call_args == mock.call(("localhost", 2003))
|
||||
|
@ -246,7 +256,8 @@ async def test_report_with_binary_state(
|
|||
"ha.test.entity.state 0.000000 12345",
|
||||
]
|
||||
hass.states.async_set("test.entity", STATE_OFF, {"foo": 1.0})
|
||||
await asyncio.sleep(0.1)
|
||||
await hass.async_block_till_done()
|
||||
hass.data[graphite.DOMAIN]._queue.join()
|
||||
|
||||
assert mock_socket.return_value.connect.call_count == 1
|
||||
assert mock_socket.return_value.connect.call_args == mock.call(("localhost", 2003))
|
||||
|
@ -282,10 +293,12 @@ async def test_send_to_graphite_errors(
|
|||
mock_socket.reset_mock()
|
||||
|
||||
await hass.async_start()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
mock_socket.return_value.connect.side_effect = error
|
||||
|
||||
hass.states.async_set("test.entity", STATE_ON)
|
||||
await asyncio.sleep(0.1)
|
||||
await hass.async_block_till_done()
|
||||
hass.data[graphite.DOMAIN]._queue.join()
|
||||
|
||||
assert log_text in caplog.text
|
||||
|
|
|
@ -71,6 +71,7 @@ async def test_system_status_subscription(
|
|||
):
|
||||
freezer.tick(TEST_TIME_ADVANCE_INTERVAL)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
response = await client.receive_json()
|
||||
assert response["event"] == {
|
||||
|
|
|
@ -239,7 +239,7 @@ async def test_receive_code(mock_debug, hass):
|
|||
},
|
||||
**PilightDaemonSim.test_message["message"],
|
||||
)
|
||||
debug_log_call = mock_debug.call_args_list[-3]
|
||||
debug_log_call = mock_debug.call_args_list[-1]
|
||||
|
||||
# Check if all message parts are put on event bus
|
||||
for key, value in expected_message.items():
|
||||
|
@ -272,7 +272,7 @@ async def test_whitelist_exact_match(mock_debug, hass):
|
|||
},
|
||||
**PilightDaemonSim.test_message["message"],
|
||||
)
|
||||
debug_log_call = mock_debug.call_args_list[-3]
|
||||
debug_log_call = mock_debug.call_args_list[-1]
|
||||
|
||||
# Check if all message parts are put on event bus
|
||||
for key, value in expected_message.items():
|
||||
|
@ -303,7 +303,7 @@ async def test_whitelist_partial_match(mock_debug, hass):
|
|||
},
|
||||
**PilightDaemonSim.test_message["message"],
|
||||
)
|
||||
debug_log_call = mock_debug.call_args_list[-3]
|
||||
debug_log_call = mock_debug.call_args_list[-1]
|
||||
|
||||
# Check if all message parts are put on event bus
|
||||
for key, value in expected_message.items():
|
||||
|
@ -337,7 +337,7 @@ async def test_whitelist_or_match(mock_debug, hass):
|
|||
},
|
||||
**PilightDaemonSim.test_message["message"],
|
||||
)
|
||||
debug_log_call = mock_debug.call_args_list[-3]
|
||||
debug_log_call = mock_debug.call_args_list[-1]
|
||||
|
||||
# Check if all message parts are put on event bus
|
||||
for key, value in expected_message.items():
|
||||
|
@ -360,7 +360,7 @@ async def test_whitelist_no_match(mock_debug, hass):
|
|||
|
||||
await hass.async_start()
|
||||
await hass.async_block_till_done()
|
||||
debug_log_call = mock_debug.call_args_list[-3]
|
||||
debug_log_call = mock_debug.call_args_list[-1]
|
||||
|
||||
assert "Event pilight_received" not in debug_log_call
|
||||
|
||||
|
|
|
@ -43,8 +43,9 @@ async def test_basic_usage(hass, tmpdir):
|
|||
return last_filename
|
||||
|
||||
with patch("cProfile.Profile"), patch.object(hass.config, "path", _mock_path):
|
||||
await hass.services.async_call(DOMAIN, SERVICE_START, {CONF_SECONDS: 0.000001})
|
||||
await hass.async_block_till_done()
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_START, {CONF_SECONDS: 0.000001}, blocking=True
|
||||
)
|
||||
|
||||
assert os.path.exists(last_filename)
|
||||
|
||||
|
@ -72,8 +73,9 @@ async def test_memory_usage(hass, tmpdir):
|
|||
return last_filename
|
||||
|
||||
with patch("guppy.hpy") as mock_hpy, patch.object(hass.config, "path", _mock_path):
|
||||
await hass.services.async_call(DOMAIN, SERVICE_MEMORY, {CONF_SECONDS: 0.000001})
|
||||
await hass.async_block_till_done()
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_MEMORY, {CONF_SECONDS: 0.000001}, blocking=True
|
||||
)
|
||||
|
||||
mock_hpy.assert_called_once()
|
||||
|
||||
|
@ -97,9 +99,8 @@ async def test_object_growth_logging(
|
|||
|
||||
with patch("objgraph.growth"):
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_START_LOG_OBJECTS, {CONF_SCAN_INTERVAL: 10}
|
||||
DOMAIN, SERVICE_START_LOG_OBJECTS, {CONF_SCAN_INTERVAL: 10}, blocking=True
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert "Growth" in caplog.text
|
||||
caplog.clear()
|
||||
|
@ -108,8 +109,7 @@ async def test_object_growth_logging(
|
|||
await hass.async_block_till_done()
|
||||
assert "Growth" in caplog.text
|
||||
|
||||
await hass.services.async_call(DOMAIN, SERVICE_STOP_LOG_OBJECTS, {})
|
||||
await hass.async_block_till_done()
|
||||
await hass.services.async_call(DOMAIN, SERVICE_STOP_LOG_OBJECTS, {}, blocking=True)
|
||||
caplog.clear()
|
||||
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=21))
|
||||
|
@ -150,9 +150,8 @@ async def test_dump_log_object(
|
|||
assert hass.services.has_service(DOMAIN, SERVICE_DUMP_LOG_OBJECTS)
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_DUMP_LOG_OBJECTS, {CONF_TYPE: "DumpLogDummy"}
|
||||
DOMAIN, SERVICE_DUMP_LOG_OBJECTS, {CONF_TYPE: "DumpLogDummy"}, blocking=True
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert "<DumpLogDummy success>" in caplog.text
|
||||
assert "Failed to serialize" in caplog.text
|
||||
|
@ -174,8 +173,7 @@ async def test_log_thread_frames(
|
|||
|
||||
assert hass.services.has_service(DOMAIN, SERVICE_LOG_THREAD_FRAMES)
|
||||
|
||||
await hass.services.async_call(DOMAIN, SERVICE_LOG_THREAD_FRAMES, {})
|
||||
await hass.async_block_till_done()
|
||||
await hass.services.async_call(DOMAIN, SERVICE_LOG_THREAD_FRAMES, {}, blocking=True)
|
||||
|
||||
assert "SyncWorker_0" in caplog.text
|
||||
caplog.clear()
|
||||
|
@ -197,8 +195,9 @@ async def test_log_scheduled(
|
|||
|
||||
assert hass.services.has_service(DOMAIN, SERVICE_LOG_EVENT_LOOP_SCHEDULED)
|
||||
|
||||
await hass.services.async_call(DOMAIN, SERVICE_LOG_EVENT_LOOP_SCHEDULED, {})
|
||||
await hass.async_block_till_done()
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_LOG_EVENT_LOOP_SCHEDULED, {}, blocking=True
|
||||
)
|
||||
|
||||
assert "Scheduled" in caplog.text
|
||||
caplog.clear()
|
||||
|
|
|
@ -815,15 +815,13 @@ async def test_wait_for_trigger_variables(hass: HomeAssistant) -> None:
|
|||
actions = [
|
||||
{
|
||||
"alias": "variables",
|
||||
"variables": {"seconds": 5},
|
||||
"variables": {"state": "off"},
|
||||
},
|
||||
{
|
||||
"alias": wait_alias,
|
||||
"wait_for_trigger": {
|
||||
"platform": "state",
|
||||
"entity_id": "switch.test",
|
||||
"to": "off",
|
||||
"for": {"seconds": "{{ seconds }}"},
|
||||
"platform": "template",
|
||||
"value_template": "{{ states.switch.test.state == state }}",
|
||||
},
|
||||
},
|
||||
]
|
||||
|
@ -839,9 +837,6 @@ async def test_wait_for_trigger_variables(hass: HomeAssistant) -> None:
|
|||
assert script_obj.is_running
|
||||
assert script_obj.last_action == wait_alias
|
||||
hass.states.async_set("switch.test", "off")
|
||||
# the script task + 2 tasks created by wait_for_trigger script step
|
||||
await hass.async_wait_for_task_count(3)
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=10))
|
||||
await hass.async_block_till_done()
|
||||
except (AssertionError, asyncio.TimeoutError):
|
||||
await script_obj.async_stop()
|
||||
|
|
|
@ -774,12 +774,10 @@ async def test_warning_logged_on_wrap_up_timeout(hass, caplog):
|
|||
|
||||
def gen_domain_setup(domain):
|
||||
async def async_setup(hass, config):
|
||||
await asyncio.sleep(0.1)
|
||||
|
||||
async def _background_task():
|
||||
await asyncio.sleep(0.2)
|
||||
|
||||
await hass.async_create_task(_background_task())
|
||||
hass.async_create_task(_background_task())
|
||||
return True
|
||||
|
||||
return async_setup
|
||||
|
|
|
@ -3559,14 +3559,17 @@ async def test_initializing_flows_canceled_on_shutdown(hass: HomeAssistant, mana
|
|||
"""Mock Reauth."""
|
||||
await asyncio.sleep(1)
|
||||
|
||||
mock_integration(hass, MockModule("test"))
|
||||
mock_entity_platform(hass, "config_flow.test", None)
|
||||
|
||||
with patch.dict(
|
||||
config_entries.HANDLERS, {"comp": MockFlowHandler, "test": MockFlowHandler}
|
||||
):
|
||||
task = asyncio.create_task(
|
||||
manager.flow.async_init("test", context={"source": "reauth"})
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await manager.flow.async_shutdown()
|
||||
await hass.async_block_till_done()
|
||||
await manager.flow.async_shutdown()
|
||||
|
||||
with pytest.raises(asyncio.exceptions.CancelledError):
|
||||
await task
|
||||
with pytest.raises(asyncio.exceptions.CancelledError):
|
||||
await task
|
||||
|
|
|
@ -124,7 +124,7 @@ def test_async_add_job_add_hass_threaded_job_to_pool() -> None:
|
|||
ha.HomeAssistant.async_add_hass_job(hass, ha.HassJob(job))
|
||||
assert len(hass.loop.call_soon.mock_calls) == 0
|
||||
assert len(hass.loop.create_task.mock_calls) == 0
|
||||
assert len(hass.loop.run_in_executor.mock_calls) == 1
|
||||
assert len(hass.loop.run_in_executor.mock_calls) == 2
|
||||
|
||||
|
||||
def test_async_create_task_schedule_coroutine(event_loop):
|
||||
|
@ -205,7 +205,7 @@ async def test_shutdown_calls_block_till_done_after_shutdown_run_callback_thread
|
|||
assert stop_calls[-1] == "async_block_till_done"
|
||||
|
||||
|
||||
async def test_pending_sheduler(hass: HomeAssistant) -> None:
|
||||
async def test_pending_scheduler(hass: HomeAssistant) -> None:
|
||||
"""Add a coro to pending tasks."""
|
||||
call_count = []
|
||||
|
||||
|
@ -216,9 +216,9 @@ async def test_pending_sheduler(hass: HomeAssistant) -> None:
|
|||
for _ in range(3):
|
||||
hass.async_add_job(test_coro())
|
||||
|
||||
await asyncio.wait(hass._pending_tasks)
|
||||
await asyncio.wait(hass._tasks)
|
||||
|
||||
assert len(hass._pending_tasks) == 3
|
||||
assert len(hass._tasks) == 0
|
||||
assert len(call_count) == 3
|
||||
|
||||
|
||||
|
@ -240,7 +240,7 @@ async def test_async_add_job_pending_tasks_coro(hass: HomeAssistant) -> None:
|
|||
|
||||
await wait_finish_callback()
|
||||
|
||||
assert len(hass._pending_tasks) == 2
|
||||
assert len(hass._tasks) == 2
|
||||
await hass.async_block_till_done()
|
||||
assert len(call_count) == 2
|
||||
|
||||
|
@ -263,7 +263,7 @@ async def test_async_create_task_pending_tasks_coro(hass: HomeAssistant) -> None
|
|||
|
||||
await wait_finish_callback()
|
||||
|
||||
assert len(hass._pending_tasks) == 2
|
||||
assert len(hass._tasks) == 2
|
||||
await hass.async_block_till_done()
|
||||
assert len(call_count) == 2
|
||||
|
||||
|
@ -286,7 +286,6 @@ async def test_async_add_job_pending_tasks_executor(hass: HomeAssistant) -> None
|
|||
|
||||
await wait_finish_callback()
|
||||
|
||||
assert len(hass._pending_tasks) == 2
|
||||
await hass.async_block_till_done()
|
||||
assert len(call_count) == 2
|
||||
|
||||
|
@ -312,7 +311,7 @@ async def test_async_add_job_pending_tasks_callback(hass: HomeAssistant) -> None
|
|||
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(hass._pending_tasks) == 0
|
||||
assert len(hass._tasks) == 0
|
||||
assert len(call_count) == 2
|
||||
|
||||
|
||||
|
@ -1144,11 +1143,10 @@ async def test_start_taking_too_long(event_loop, caplog):
|
|||
"""Test when async_start takes too long."""
|
||||
hass = ha.HomeAssistant()
|
||||
caplog.set_level(logging.WARNING)
|
||||
hass.async_create_task(asyncio.sleep(0))
|
||||
|
||||
try:
|
||||
with patch.object(
|
||||
hass, "async_block_till_done", side_effect=asyncio.TimeoutError
|
||||
):
|
||||
with patch("asyncio.wait", return_value=(set(), {asyncio.Future()})):
|
||||
await hass.async_start()
|
||||
|
||||
assert hass.state == ha.CoreState.running
|
||||
|
@ -1159,21 +1157,6 @@ async def test_start_taking_too_long(event_loop, caplog):
|
|||
assert hass.state == ha.CoreState.stopped
|
||||
|
||||
|
||||
async def test_track_task_functions(event_loop):
|
||||
"""Test function to start/stop track task and initial state."""
|
||||
hass = ha.HomeAssistant()
|
||||
try:
|
||||
assert hass._track_task
|
||||
|
||||
hass.async_stop_track_tasks()
|
||||
assert not hass._track_task
|
||||
|
||||
hass.async_track_tasks()
|
||||
assert hass._track_task
|
||||
finally:
|
||||
await hass.async_stop()
|
||||
|
||||
|
||||
async def test_service_executed_with_subservices(hass: HomeAssistant) -> None:
|
||||
"""Test we block correctly till all services done."""
|
||||
calls = async_mock_service(hass, "test", "inner")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue