mirror of
https://github.com/home-assistant/core.git
synced 2026-09-27 18:08:37 -04:00
Avoid calling extract_stack in system_log since it does blocking I/O (#100455)
This commit is contained in:
@@ -4,6 +4,7 @@ from __future__ import annotations
|
||||
import asyncio
|
||||
from collections.abc import Awaitable
|
||||
import logging
|
||||
import re
|
||||
import traceback
|
||||
from typing import Any
|
||||
from unittest.mock import MagicMock, patch
|
||||
@@ -87,11 +88,6 @@ class WatchLogErrorHandler(system_log.LogErrorHandler):
|
||||
self.watch_event.set()
|
||||
|
||||
|
||||
def get_frame(name):
|
||||
"""Get log stack frame."""
|
||||
return (name, 5, None, None)
|
||||
|
||||
|
||||
async def async_setup_system_log(hass, config) -> WatchLogErrorHandler:
|
||||
"""Set up the system_log component."""
|
||||
WatchLogErrorHandler.instances = []
|
||||
@@ -362,21 +358,28 @@ async def test_unknown_path(
|
||||
assert log["source"] == ["unknown_path", 0]
|
||||
|
||||
|
||||
def get_frame(path: str, previous_frame: MagicMock | None) -> MagicMock:
|
||||
"""Get log stack frame."""
|
||||
return MagicMock(
|
||||
f_back=previous_frame,
|
||||
f_code=MagicMock(co_filename=path),
|
||||
f_lineno=5,
|
||||
)
|
||||
|
||||
|
||||
async def async_log_error_from_test_path(hass, path, watcher):
|
||||
"""Log error while mocking the path."""
|
||||
call_path = "internal_path.py"
|
||||
main_frame = get_frame("main_path/main.py", None)
|
||||
path_frame = get_frame(path, main_frame)
|
||||
call_path_frame = get_frame(call_path, path_frame)
|
||||
logger_frame = get_frame("venv_path/logging/log.py", call_path_frame)
|
||||
|
||||
with patch.object(
|
||||
_LOGGER, "findCaller", MagicMock(return_value=(call_path, 0, None, None))
|
||||
), patch(
|
||||
"traceback.extract_stack",
|
||||
MagicMock(
|
||||
return_value=[
|
||||
get_frame("main_path/main.py"),
|
||||
get_frame(path),
|
||||
get_frame(call_path),
|
||||
get_frame("venv_path/logging/log.py"),
|
||||
]
|
||||
),
|
||||
"homeassistant.components.system_log.sys._getframe",
|
||||
return_value=logger_frame,
|
||||
):
|
||||
wait_empty = watcher.add_watcher("error message")
|
||||
_LOGGER.error("error message")
|
||||
@@ -441,3 +444,28 @@ async def test_raise_during_log_capture(
|
||||
log = find_log(await get_error_log(hass_ws_client), "ERROR")
|
||||
assert log is not None
|
||||
assert_log(log, "", "Bad logger message: repr error", "ERROR")
|
||||
|
||||
|
||||
async def test__figure_out_source(hass: HomeAssistant) -> None:
|
||||
"""Test that source is figured out correctly.
|
||||
|
||||
We have to test this directly for exception tracebacks since
|
||||
we cannot generate a trackback from a Home Assistant component
|
||||
in a test because the test is not a component.
|
||||
"""
|
||||
try:
|
||||
raise ValueError("test")
|
||||
except ValueError as ex:
|
||||
exc_info = (type(ex), ex, ex.__traceback__)
|
||||
mock_record = MagicMock(
|
||||
pathname="should not hit",
|
||||
lineno=5,
|
||||
exc_info=exc_info,
|
||||
)
|
||||
regex_str = f"({__file__})"
|
||||
file, line_no = system_log._figure_out_source(
|
||||
mock_record,
|
||||
re.compile(regex_str),
|
||||
)
|
||||
assert file == __file__
|
||||
assert line_no != 5
|
||||
|
||||
Reference in New Issue
Block a user