2020-05-13 07:58:33 +00:00
|
|
|
"""Test the frame helper."""
|
2023-01-22 16:26:24 +00:00
|
|
|
|
2023-10-03 17:21:27 +00:00
|
|
|
from collections.abc import Generator
|
2021-01-01 21:31:56 +00:00
|
|
|
from unittest.mock import Mock, patch
|
|
|
|
|
2020-05-13 07:58:33 +00:00
|
|
|
import pytest
|
|
|
|
|
|
|
|
from homeassistant.helpers import frame
|
|
|
|
|
|
|
|
|
2023-10-03 17:21:27 +00:00
|
|
|
@pytest.fixture
|
|
|
|
def mock_integration_frame() -> Generator[Mock, None, None]:
|
|
|
|
"""Mock as if we're calling code from inside an integration."""
|
|
|
|
correct_frame = Mock(
|
|
|
|
filename="/home/paulus/homeassistant/components/hue/light.py",
|
|
|
|
lineno="23",
|
|
|
|
line="self.light.is_on",
|
|
|
|
)
|
|
|
|
with patch(
|
|
|
|
"homeassistant.helpers.frame.extract_stack",
|
|
|
|
return_value=[
|
|
|
|
Mock(
|
|
|
|
filename="/home/paulus/homeassistant/core.py",
|
|
|
|
lineno="23",
|
|
|
|
line="do_something()",
|
|
|
|
),
|
|
|
|
correct_frame,
|
|
|
|
Mock(
|
|
|
|
filename="/home/paulus/aiohue/lights.py",
|
|
|
|
lineno="2",
|
|
|
|
line="something()",
|
|
|
|
),
|
|
|
|
],
|
|
|
|
):
|
|
|
|
yield correct_frame
|
|
|
|
|
|
|
|
|
2023-02-11 12:48:53 +00:00
|
|
|
async def test_extract_frame_integration(
|
|
|
|
caplog: pytest.LogCaptureFixture, mock_integration_frame: Mock
|
|
|
|
) -> None:
|
2020-05-13 07:58:33 +00:00
|
|
|
"""Test extracting the current frame from integration context."""
|
2023-10-03 17:21:27 +00:00
|
|
|
integration_frame = frame.get_integration_frame()
|
|
|
|
assert integration_frame == frame.IntegrationFrame(
|
|
|
|
False, "homeassistant/components/hue/light.py", mock_integration_frame, "hue"
|
|
|
|
)
|
2020-05-13 07:58:33 +00:00
|
|
|
|
|
|
|
|
2023-02-20 10:42:56 +00:00
|
|
|
async def test_extract_frame_integration_with_excluded_integration(
|
|
|
|
caplog: pytest.LogCaptureFixture,
|
|
|
|
) -> None:
|
2020-08-12 14:08:33 +00:00
|
|
|
"""Test extracting the current frame from integration context."""
|
|
|
|
correct_frame = Mock(
|
|
|
|
filename="/home/dev/homeassistant/components/mdns/light.py",
|
|
|
|
lineno="23",
|
|
|
|
line="self.light.is_on",
|
|
|
|
)
|
|
|
|
with patch(
|
|
|
|
"homeassistant.helpers.frame.extract_stack",
|
|
|
|
return_value=[
|
|
|
|
Mock(
|
|
|
|
filename="/home/dev/homeassistant/core.py",
|
|
|
|
lineno="23",
|
|
|
|
line="do_something()",
|
|
|
|
),
|
|
|
|
correct_frame,
|
|
|
|
Mock(
|
|
|
|
filename="/home/dev/homeassistant/components/zeroconf/usage.py",
|
|
|
|
lineno="23",
|
|
|
|
line="self.light.is_on",
|
|
|
|
),
|
2020-08-27 11:56:20 +00:00
|
|
|
Mock(
|
|
|
|
filename="/home/dev/mdns/lights.py",
|
|
|
|
lineno="2",
|
|
|
|
line="something()",
|
|
|
|
),
|
2020-08-12 14:08:33 +00:00
|
|
|
],
|
|
|
|
):
|
2023-10-03 17:21:27 +00:00
|
|
|
integration_frame = frame.get_integration_frame(
|
2020-08-12 14:08:33 +00:00
|
|
|
exclude_integrations={"zeroconf"}
|
|
|
|
)
|
|
|
|
|
2023-10-03 17:21:27 +00:00
|
|
|
assert integration_frame == frame.IntegrationFrame(
|
|
|
|
False, "homeassistant/components/mdns/light.py", correct_frame, "mdns"
|
|
|
|
)
|
2020-08-12 14:08:33 +00:00
|
|
|
|
|
|
|
|
2023-02-20 10:42:56 +00:00
|
|
|
async def test_extract_frame_no_integration(caplog: pytest.LogCaptureFixture) -> None:
|
2020-05-13 07:58:33 +00:00
|
|
|
"""Test extracting the current frame without integration context."""
|
|
|
|
with patch(
|
|
|
|
"homeassistant.helpers.frame.extract_stack",
|
|
|
|
return_value=[
|
|
|
|
Mock(
|
|
|
|
filename="/home/paulus/homeassistant/core.py",
|
|
|
|
lineno="23",
|
|
|
|
line="do_something()",
|
|
|
|
),
|
|
|
|
Mock(
|
|
|
|
filename="/home/paulus/aiohue/lights.py",
|
|
|
|
lineno="2",
|
|
|
|
line="something()",
|
|
|
|
),
|
|
|
|
],
|
|
|
|
), pytest.raises(frame.MissingIntegrationFrame):
|
|
|
|
frame.get_integration_frame()
|
2021-12-06 23:26:31 +00:00
|
|
|
|
|
|
|
|
|
|
|
@patch.object(frame, "_REPORTED_INTEGRATIONS", set())
|
2023-10-03 17:21:27 +00:00
|
|
|
async def test_prevent_flooding(
|
|
|
|
caplog: pytest.LogCaptureFixture, mock_integration_frame: Mock
|
|
|
|
) -> None:
|
2021-12-06 23:26:31 +00:00
|
|
|
"""Test to ensure a report is only written once to the log."""
|
|
|
|
|
|
|
|
what = "accessed hi instead of hello"
|
|
|
|
key = "/home/paulus/homeassistant/components/hue/light.py:23"
|
2023-10-03 17:21:27 +00:00
|
|
|
integration = "hue"
|
|
|
|
filename = "homeassistant/components/hue/light.py"
|
|
|
|
|
|
|
|
expected_message = (
|
|
|
|
f"Detected integration that {what}. Please report issue for {integration} using"
|
|
|
|
f" this method at {filename}, line "
|
|
|
|
f"{mock_integration_frame.lineno}: {mock_integration_frame.line}"
|
|
|
|
)
|
2021-12-06 23:26:31 +00:00
|
|
|
|
|
|
|
frame.report(what, error_if_core=False)
|
2023-10-03 17:21:27 +00:00
|
|
|
assert expected_message in caplog.text
|
2021-12-06 23:26:31 +00:00
|
|
|
assert key in frame._REPORTED_INTEGRATIONS
|
|
|
|
assert len(frame._REPORTED_INTEGRATIONS) == 1
|
|
|
|
|
|
|
|
caplog.clear()
|
|
|
|
|
|
|
|
frame.report(what, error_if_core=False)
|
2023-10-03 17:21:27 +00:00
|
|
|
assert expected_message not in caplog.text
|
2021-12-06 23:26:31 +00:00
|
|
|
assert key in frame._REPORTED_INTEGRATIONS
|
|
|
|
assert len(frame._REPORTED_INTEGRATIONS) == 1
|
2022-02-18 08:05:38 +00:00
|
|
|
|
|
|
|
|
2023-02-20 10:42:56 +00:00
|
|
|
async def test_report_missing_integration_frame(
|
|
|
|
caplog: pytest.LogCaptureFixture,
|
|
|
|
) -> None:
|
2022-02-18 08:05:38 +00:00
|
|
|
"""Test reporting when no integration is detected."""
|
|
|
|
|
|
|
|
what = "teststring"
|
|
|
|
with patch(
|
|
|
|
"homeassistant.helpers.frame.get_integration_frame",
|
|
|
|
side_effect=frame.MissingIntegrationFrame,
|
|
|
|
):
|
|
|
|
frame.report(what, error_if_core=False)
|
|
|
|
assert what in caplog.text
|
|
|
|
assert caplog.text.count(what) == 1
|