core/tests/components/ffmpeg/test_init.py

239 lines
7.7 KiB
Python

"""The tests for Home Assistant ffmpeg."""
from unittest.mock import AsyncMock, MagicMock, Mock, call, patch
from homeassistant.components import ffmpeg
from homeassistant.components.ffmpeg import (
DOMAIN,
SERVICE_RESTART,
SERVICE_START,
SERVICE_STOP,
)
from homeassistant.const import ATTR_ENTITY_ID
from homeassistant.core import callback
from homeassistant.setup import async_setup_component, setup_component
from tests.common import assert_setup_component, get_test_home_assistant
@callback
def async_start(hass, entity_id=None):
"""Start a FFmpeg process on entity.
This is a legacy helper method. Do not use it for new tests.
"""
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
hass.async_add_job(hass.services.async_call(DOMAIN, SERVICE_START, data))
@callback
def async_stop(hass, entity_id=None):
"""Stop a FFmpeg process on entity.
This is a legacy helper method. Do not use it for new tests.
"""
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
hass.async_add_job(hass.services.async_call(DOMAIN, SERVICE_STOP, data))
@callback
def async_restart(hass, entity_id=None):
"""Restart a FFmpeg process on entity.
This is a legacy helper method. Do not use it for new tests.
"""
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
hass.async_add_job(hass.services.async_call(DOMAIN, SERVICE_RESTART, data))
class MockFFmpegDev(ffmpeg.FFmpegBase):
"""FFmpeg device mock."""
def __init__(self, hass, initial_state=True, entity_id="test.ffmpeg_device"):
"""Initialize mock."""
super().__init__(initial_state)
self.hass = hass
self.entity_id = entity_id
self.ffmpeg = MagicMock
self.called_stop = False
self.called_start = False
self.called_restart = False
self.called_entities = None
async def _async_start_ffmpeg(self, entity_ids):
"""Mock start."""
self.called_start = True
self.called_entities = entity_ids
async def _async_stop_ffmpeg(self, entity_ids):
"""Mock stop."""
self.called_stop = True
self.called_entities = entity_ids
class TestFFmpegSetup:
"""Test class for ffmpeg."""
def setup_method(self):
"""Set up things to be run when tests are started."""
self.hass = get_test_home_assistant()
def teardown_method(self):
"""Stop everything that was started."""
self.hass.stop()
def test_setup_component(self):
"""Set up ffmpeg component."""
with assert_setup_component(1):
setup_component(self.hass, ffmpeg.DOMAIN, {ffmpeg.DOMAIN: {}})
assert self.hass.data[ffmpeg.DATA_FFMPEG].binary == "ffmpeg"
def test_setup_component_test_service(self):
"""Set up ffmpeg component test services."""
with assert_setup_component(1):
setup_component(self.hass, ffmpeg.DOMAIN, {ffmpeg.DOMAIN: {}})
assert self.hass.services.has_service(ffmpeg.DOMAIN, "start")
assert self.hass.services.has_service(ffmpeg.DOMAIN, "stop")
assert self.hass.services.has_service(ffmpeg.DOMAIN, "restart")
async def test_setup_component_test_register(hass):
"""Set up ffmpeg component test register."""
with assert_setup_component(1):
await async_setup_component(hass, ffmpeg.DOMAIN, {ffmpeg.DOMAIN: {}})
hass.bus.async_listen_once = MagicMock()
ffmpeg_dev = MockFFmpegDev(hass)
await ffmpeg_dev.async_added_to_hass()
assert hass.bus.async_listen_once.called
assert hass.bus.async_listen_once.call_count == 2
async def test_setup_component_test_register_no_startup(hass):
"""Set up ffmpeg component test register without startup."""
with assert_setup_component(1):
await async_setup_component(hass, ffmpeg.DOMAIN, {ffmpeg.DOMAIN: {}})
hass.bus.async_listen_once = MagicMock()
ffmpeg_dev = MockFFmpegDev(hass, False)
await ffmpeg_dev.async_added_to_hass()
assert hass.bus.async_listen_once.called
assert hass.bus.async_listen_once.call_count == 1
async def test_setup_component_test_service_start(hass):
"""Set up ffmpeg component test service start."""
with assert_setup_component(1):
await async_setup_component(hass, ffmpeg.DOMAIN, {ffmpeg.DOMAIN: {}})
ffmpeg_dev = MockFFmpegDev(hass, False)
await ffmpeg_dev.async_added_to_hass()
async_start(hass)
await hass.async_block_till_done()
assert ffmpeg_dev.called_start
async def test_setup_component_test_service_stop(hass):
"""Set up ffmpeg component test service stop."""
with assert_setup_component(1):
await async_setup_component(hass, ffmpeg.DOMAIN, {ffmpeg.DOMAIN: {}})
ffmpeg_dev = MockFFmpegDev(hass, False)
await ffmpeg_dev.async_added_to_hass()
async_stop(hass)
await hass.async_block_till_done()
assert ffmpeg_dev.called_stop
async def test_setup_component_test_service_restart(hass):
"""Set up ffmpeg component test service restart."""
with assert_setup_component(1):
await async_setup_component(hass, ffmpeg.DOMAIN, {ffmpeg.DOMAIN: {}})
ffmpeg_dev = MockFFmpegDev(hass, False)
await ffmpeg_dev.async_added_to_hass()
async_restart(hass)
await hass.async_block_till_done()
assert ffmpeg_dev.called_stop
assert ffmpeg_dev.called_start
async def test_setup_component_test_service_start_with_entity(hass):
"""Set up ffmpeg component test service start."""
with assert_setup_component(1):
await async_setup_component(hass, ffmpeg.DOMAIN, {ffmpeg.DOMAIN: {}})
ffmpeg_dev = MockFFmpegDev(hass, False)
await ffmpeg_dev.async_added_to_hass()
async_start(hass, "test.ffmpeg_device")
await hass.async_block_till_done()
assert ffmpeg_dev.called_start
assert ffmpeg_dev.called_entities == ["test.ffmpeg_device"]
async def test_async_get_image_with_width_height(hass):
"""Test fetching an image with a specific width and height."""
with assert_setup_component(1):
await async_setup_component(hass, ffmpeg.DOMAIN, {ffmpeg.DOMAIN: {}})
get_image_mock = AsyncMock()
with patch(
"homeassistant.components.ffmpeg.ImageFrame",
return_value=Mock(get_image=get_image_mock),
):
await ffmpeg.async_get_image(hass, "rtsp://fake", width=640, height=480)
assert get_image_mock.call_args_list == [
call("rtsp://fake", output_format="mjpeg", extra_cmd="-s 640x480")
]
async def test_async_get_image_with_extra_cmd_overlapping_width_height(hass):
"""Test fetching an image with and extra_cmd with width and height and a specific width and height."""
with assert_setup_component(1):
await async_setup_component(hass, ffmpeg.DOMAIN, {ffmpeg.DOMAIN: {}})
get_image_mock = AsyncMock()
with patch(
"homeassistant.components.ffmpeg.ImageFrame",
return_value=Mock(get_image=get_image_mock),
):
await ffmpeg.async_get_image(
hass, "rtsp://fake", extra_cmd="-s 1024x768", width=640, height=480
)
assert get_image_mock.call_args_list == [
call("rtsp://fake", output_format="mjpeg", extra_cmd="-s 1024x768")
]
async def test_async_get_image_with_extra_cmd_width_height(hass):
"""Test fetching an image with and extra_cmd and a specific width and height."""
with assert_setup_component(1):
await async_setup_component(hass, ffmpeg.DOMAIN, {ffmpeg.DOMAIN: {}})
get_image_mock = AsyncMock()
with patch(
"homeassistant.components.ffmpeg.ImageFrame",
return_value=Mock(get_image=get_image_mock),
):
await ffmpeg.async_get_image(
hass, "rtsp://fake", extra_cmd="-vf any", width=640, height=480
)
assert get_image_mock.call_args_list == [
call("rtsp://fake", output_format="mjpeg", extra_cmd="-vf any -s 640x480")
]