2017-10-03 03:25:04 +00:00
|
|
|
"""Test Home Assistant logging util methods."""
|
|
|
|
import asyncio
|
2021-04-01 23:22:08 +00:00
|
|
|
from functools import partial
|
2017-10-03 03:25:04 +00:00
|
|
|
import logging
|
2020-05-16 14:29:58 +00:00
|
|
|
import queue
|
2021-01-01 21:31:56 +00:00
|
|
|
from unittest.mock import patch
|
2017-10-03 03:25:04 +00:00
|
|
|
|
2020-05-06 21:14:57 +00:00
|
|
|
import pytest
|
|
|
|
|
2021-04-15 08:53:48 +00:00
|
|
|
from homeassistant.const import EVENT_HOMEASSISTANT_CLOSE
|
2021-04-01 23:22:08 +00:00
|
|
|
from homeassistant.core import callback, is_callback
|
2017-10-03 03:25:04 +00:00
|
|
|
import homeassistant.util.logging as logging_util
|
|
|
|
|
|
|
|
|
|
|
|
def test_sensitive_data_filter():
|
|
|
|
"""Test the logging sensitive data filter."""
|
2019-07-31 19:25:30 +00:00
|
|
|
log_filter = logging_util.HideSensitiveDataFilter("mock_sensitive")
|
2017-10-03 03:25:04 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
clean_record = logging.makeLogRecord({"msg": "clean log data"})
|
2017-10-03 03:25:04 +00:00
|
|
|
log_filter.filter(clean_record)
|
|
|
|
assert clean_record.msg == "clean log data"
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
sensitive_record = logging.makeLogRecord({"msg": "mock_sensitive log"})
|
2017-10-03 03:25:04 +00:00
|
|
|
log_filter.filter(sensitive_record)
|
|
|
|
assert sensitive_record.msg == "******* log"
|
|
|
|
|
|
|
|
|
2020-05-16 14:29:58 +00:00
|
|
|
async def test_logging_with_queue_handler():
|
|
|
|
"""Test logging with HomeAssistantQueueHandler."""
|
2017-10-03 03:25:04 +00:00
|
|
|
|
2020-05-16 14:29:58 +00:00
|
|
|
simple_queue = queue.SimpleQueue() # type: ignore
|
|
|
|
handler = logging_util.HomeAssistantQueueHandler(simple_queue)
|
2017-10-03 03:25:04 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
log_record = logging.makeLogRecord({"msg": "Test Log Record"})
|
2020-05-16 14:29:58 +00:00
|
|
|
|
2017-10-03 03:25:04 +00:00
|
|
|
handler.emit(log_record)
|
|
|
|
|
2020-05-16 14:29:58 +00:00
|
|
|
with pytest.raises(asyncio.CancelledError), patch.object(
|
|
|
|
handler, "enqueue", side_effect=asyncio.CancelledError
|
|
|
|
):
|
|
|
|
handler.emit(log_record)
|
|
|
|
|
2020-05-17 12:39:27 +00:00
|
|
|
with patch.object(handler, "emit") as emit_mock:
|
|
|
|
handler.handle(log_record)
|
|
|
|
emit_mock.assert_called_once()
|
|
|
|
|
|
|
|
with patch.object(handler, "filter") as filter_mock, patch.object(
|
|
|
|
handler, "emit"
|
|
|
|
) as emit_mock:
|
|
|
|
filter_mock.return_value = False
|
|
|
|
handler.handle(log_record)
|
|
|
|
emit_mock.assert_not_called()
|
|
|
|
|
2020-05-16 14:29:58 +00:00
|
|
|
with patch.object(handler, "enqueue", side_effect=OSError), patch.object(
|
|
|
|
handler, "handleError"
|
|
|
|
) as mock_handle_error:
|
|
|
|
handler.emit(log_record)
|
|
|
|
mock_handle_error.assert_called_once()
|
2017-10-03 03:25:04 +00:00
|
|
|
|
2020-05-16 14:29:58 +00:00
|
|
|
handler.close()
|
2017-10-03 03:25:04 +00:00
|
|
|
|
2020-05-16 14:29:58 +00:00
|
|
|
assert simple_queue.get_nowait().msg == "Test Log Record"
|
|
|
|
assert simple_queue.empty()
|
2017-10-03 03:25:04 +00:00
|
|
|
|
|
|
|
|
2020-05-16 14:29:58 +00:00
|
|
|
async def test_migrate_log_handler(hass):
|
|
|
|
"""Test migrating log handlers."""
|
2017-10-03 03:25:04 +00:00
|
|
|
|
2021-04-15 08:53:48 +00:00
|
|
|
original_handlers = logging.root.handlers
|
|
|
|
|
2020-05-16 14:29:58 +00:00
|
|
|
logging_util.async_activate_log_queue_handler(hass)
|
2017-10-03 03:25:04 +00:00
|
|
|
|
2020-05-16 14:29:58 +00:00
|
|
|
assert len(logging.root.handlers) == 1
|
|
|
|
assert isinstance(logging.root.handlers[0], logging_util.HomeAssistantQueueHandler)
|
2019-04-29 16:53:22 +00:00
|
|
|
|
2021-04-15 08:53:48 +00:00
|
|
|
hass.bus.async_fire(EVENT_HOMEASSISTANT_CLOSE)
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
|
|
assert logging.root.handlers == original_handlers
|
|
|
|
|
2019-04-29 16:53:22 +00:00
|
|
|
|
2020-05-06 21:14:57 +00:00
|
|
|
@pytest.mark.no_fail_on_log_exception
|
2019-04-29 16:53:22 +00:00
|
|
|
async def test_async_create_catching_coro(hass, caplog):
|
|
|
|
"""Test exception logging of wrapped coroutine."""
|
2019-07-31 19:25:30 +00:00
|
|
|
|
2019-04-29 16:53:22 +00:00
|
|
|
async def job():
|
2019-07-31 19:25:30 +00:00
|
|
|
raise Exception("This is a bad coroutine")
|
2019-04-29 16:53:22 +00:00
|
|
|
|
|
|
|
hass.async_create_task(logging_util.async_create_catching_coro(job()))
|
|
|
|
await hass.async_block_till_done()
|
2019-07-31 19:25:30 +00:00
|
|
|
assert "This is a bad coroutine" in caplog.text
|
2019-10-05 09:59:34 +00:00
|
|
|
assert "in test_async_create_catching_coro" in caplog.text
|
2021-04-01 23:22:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_catch_log_exception():
|
|
|
|
"""Test it is still a callback after wrapping including partial."""
|
|
|
|
|
|
|
|
async def async_meth():
|
|
|
|
pass
|
|
|
|
|
|
|
|
assert asyncio.iscoroutinefunction(
|
|
|
|
logging_util.catch_log_exception(partial(async_meth), lambda: None)
|
|
|
|
)
|
|
|
|
|
|
|
|
@callback
|
|
|
|
def callback_meth():
|
|
|
|
pass
|
|
|
|
|
|
|
|
assert is_callback(
|
|
|
|
logging_util.catch_log_exception(partial(callback_meth), lambda: None)
|
|
|
|
)
|
|
|
|
|
|
|
|
def sync_meth():
|
|
|
|
pass
|
|
|
|
|
|
|
|
wrapped = logging_util.catch_log_exception(partial(sync_meth), lambda: None)
|
|
|
|
|
|
|
|
assert not is_callback(wrapped)
|
|
|
|
assert not asyncio.iscoroutinefunction(wrapped)
|