Add additional blocking operations to loop protection (#124017)
parent
14a3217d7e
commit
cb8a6af12d
|
@ -8,6 +8,7 @@ import glob
|
|||
from http.client import HTTPConnection
|
||||
import importlib
|
||||
import os
|
||||
from pathlib import Path
|
||||
from ssl import SSLContext
|
||||
import sys
|
||||
import threading
|
||||
|
@ -162,6 +163,60 @@ _BLOCKING_CALLS: tuple[BlockingCall, ...] = (
|
|||
strict_core=False,
|
||||
skip_for_tests=True,
|
||||
),
|
||||
BlockingCall(
|
||||
original_func=SSLContext.load_cert_chain,
|
||||
object=SSLContext,
|
||||
function="load_cert_chain",
|
||||
check_allowed=None,
|
||||
strict=False,
|
||||
strict_core=False,
|
||||
skip_for_tests=True,
|
||||
),
|
||||
BlockingCall(
|
||||
original_func=Path.open,
|
||||
object=Path,
|
||||
function="open",
|
||||
check_allowed=_check_file_allowed,
|
||||
strict=False,
|
||||
strict_core=False,
|
||||
skip_for_tests=True,
|
||||
),
|
||||
BlockingCall(
|
||||
original_func=Path.read_text,
|
||||
object=Path,
|
||||
function="read_text",
|
||||
check_allowed=_check_file_allowed,
|
||||
strict=False,
|
||||
strict_core=False,
|
||||
skip_for_tests=True,
|
||||
),
|
||||
BlockingCall(
|
||||
original_func=Path.read_bytes,
|
||||
object=Path,
|
||||
function="read_bytes",
|
||||
check_allowed=_check_file_allowed,
|
||||
strict=False,
|
||||
strict_core=False,
|
||||
skip_for_tests=True,
|
||||
),
|
||||
BlockingCall(
|
||||
original_func=Path.write_text,
|
||||
object=Path,
|
||||
function="write_text",
|
||||
check_allowed=_check_file_allowed,
|
||||
strict=False,
|
||||
strict_core=False,
|
||||
skip_for_tests=True,
|
||||
),
|
||||
BlockingCall(
|
||||
original_func=Path.write_bytes,
|
||||
object=Path,
|
||||
function="write_bytes",
|
||||
check_allowed=_check_file_allowed,
|
||||
strict=False,
|
||||
strict_core=False,
|
||||
skip_for_tests=True,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -218,6 +218,17 @@ async def test_protect_loop_open(caplog: pytest.LogCaptureFixture) -> None:
|
|||
assert "Detected blocking call to open with args" not in caplog.text
|
||||
|
||||
|
||||
async def test_protect_loop_path_open(caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test opening a file in /proc is not reported."""
|
||||
block_async_io.enable()
|
||||
with (
|
||||
contextlib.suppress(FileNotFoundError),
|
||||
Path("/proc/does_not_exist").open(encoding="utf8"), # noqa: ASYNC230
|
||||
):
|
||||
pass
|
||||
assert "Detected blocking call to open with args" not in caplog.text
|
||||
|
||||
|
||||
async def test_protect_open(caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test opening a file in the event loop logs."""
|
||||
with patch.object(block_async_io, "_IN_TESTS", False):
|
||||
|
@ -231,6 +242,71 @@ async def test_protect_open(caplog: pytest.LogCaptureFixture) -> None:
|
|||
assert "Detected blocking call to open with args" in caplog.text
|
||||
|
||||
|
||||
async def test_protect_path_open(caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test opening a file in the event loop logs."""
|
||||
with patch.object(block_async_io, "_IN_TESTS", False):
|
||||
block_async_io.enable()
|
||||
with (
|
||||
contextlib.suppress(FileNotFoundError),
|
||||
Path("/config/data_not_exist").open(encoding="utf8"), # noqa: ASYNC230
|
||||
):
|
||||
pass
|
||||
|
||||
assert "Detected blocking call to open with args" in caplog.text
|
||||
|
||||
|
||||
async def test_protect_path_read_bytes(caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test reading file bytes in the event loop logs."""
|
||||
with patch.object(block_async_io, "_IN_TESTS", False):
|
||||
block_async_io.enable()
|
||||
with (
|
||||
contextlib.suppress(FileNotFoundError),
|
||||
Path("/config/data_not_exist").read_bytes(), # noqa: ASYNC230
|
||||
):
|
||||
pass
|
||||
|
||||
assert "Detected blocking call to read_bytes with args" in caplog.text
|
||||
|
||||
|
||||
async def test_protect_path_read_text(caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test reading a file text in the event loop logs."""
|
||||
with patch.object(block_async_io, "_IN_TESTS", False):
|
||||
block_async_io.enable()
|
||||
with (
|
||||
contextlib.suppress(FileNotFoundError),
|
||||
Path("/config/data_not_exist").read_text(encoding="utf8"), # noqa: ASYNC230
|
||||
):
|
||||
pass
|
||||
|
||||
assert "Detected blocking call to read_text with args" in caplog.text
|
||||
|
||||
|
||||
async def test_protect_path_write_bytes(caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test writing file bytes in the event loop logs."""
|
||||
with patch.object(block_async_io, "_IN_TESTS", False):
|
||||
block_async_io.enable()
|
||||
with (
|
||||
contextlib.suppress(FileNotFoundError),
|
||||
Path("/config/data/not/exist").write_bytes(b"xxx"), # noqa: ASYNC230
|
||||
):
|
||||
pass
|
||||
|
||||
assert "Detected blocking call to write_bytes with args" in caplog.text
|
||||
|
||||
|
||||
async def test_protect_path_write_text(caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test writing file text in the event loop logs."""
|
||||
with patch.object(block_async_io, "_IN_TESTS", False):
|
||||
block_async_io.enable()
|
||||
with (
|
||||
contextlib.suppress(FileNotFoundError),
|
||||
Path("/config/data/not/exist").write_text("xxx", encoding="utf8"), # noqa: ASYNC230
|
||||
):
|
||||
pass
|
||||
|
||||
assert "Detected blocking call to write_text with args" in caplog.text
|
||||
|
||||
|
||||
async def test_enable_multiple_times(caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test trying to enable multiple times."""
|
||||
with patch.object(block_async_io, "_IN_TESTS", False):
|
||||
|
@ -354,6 +430,18 @@ async def test_protect_loop_load_verify_locations(
|
|||
assert "Detected blocking call to load_verify_locations" in caplog.text
|
||||
|
||||
|
||||
async def test_protect_loop_load_cert_chain(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
|
||||
) -> None:
|
||||
"""Test SSLContext.load_cert_chain calls in the loop are logged."""
|
||||
with patch.object(block_async_io, "_IN_TESTS", False):
|
||||
block_async_io.enable()
|
||||
context = ssl.create_default_context()
|
||||
with pytest.raises(OSError):
|
||||
context.load_cert_chain("/dev/null")
|
||||
assert "Detected blocking call to load_cert_chain" in caplog.text
|
||||
|
||||
|
||||
async def test_open_calls_ignored_in_tests(caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test opening a file in tests is ignored."""
|
||||
assert block_async_io._IN_TESTS
|
||||
|
|
Loading…
Reference in New Issue