async def test_stream_stopped_while_decoding(hass): """Tests that worker quits when stop() is called while decodign.""" # Add some synchronization so that the test can pause the background # worker. When the worker is stopped, the test invokes stop() which # will cause the worker thread to exit once it enters the decode # loop worker_open = threading.Event() worker_wake = threading.Event() stream = Stream(hass, STREAM_SOURCE, {}) stream.add_provider(HLS_PROVIDER) py_av = MockPyAv() py_av.container.packets = PacketSequence(TEST_SEQUENCE_LENGTH) def blocking_open(stream_source, *args, **kwargs): # Let test know the thread is running worker_open.set() # Block worker thread until test wakes up worker_wake.wait() return py_av.open(stream_source, args, kwargs) with patch("av.open", new=blocking_open): stream.start() assert worker_open.wait(TIMEOUT) # Note: There is a race here where the worker could start as soon # as the wake event is sent, completing all decode work. worker_wake.set() stream.stop()
async def test_update_stream_source(hass): """Tests that the worker is re-invoked when the stream source is updated.""" worker_open = threading.Event() worker_wake = threading.Event() stream = Stream(hass, STREAM_SOURCE, {}) stream.add_provider(HLS_PROVIDER) # Note that keepalive is not set here. The stream is "restarted" even though # it is not stopping due to failure. py_av = MockPyAv() py_av.container.packets = PacketSequence(TEST_SEQUENCE_LENGTH) last_stream_source = None def blocking_open(stream_source, *args, **kwargs): nonlocal last_stream_source if not isinstance(stream_source, io.BytesIO): last_stream_source = stream_source # Let test know the thread is running worker_open.set() # Block worker thread until test wakes up worker_wake.wait() return py_av.open(stream_source, args, kwargs) with patch("av.open", new=blocking_open), patch( "homeassistant.components.stream.worker.SegmentBuffer.check_flush_part", side_effect=MockFlushPart.wrapped_check_flush_part, autospec=True, ): stream.start() assert worker_open.wait(TIMEOUT) assert last_stream_source == STREAM_SOURCE # Update the stream source, then the test wakes up the worker and assert # that it re-opens the new stream (the test again waits on thread_started) worker_open.clear() stream.update_source(STREAM_SOURCE + "-updated-source") worker_wake.set() assert worker_open.wait(TIMEOUT) assert last_stream_source == STREAM_SOURCE + "-updated-source" worker_wake.set() # Cleanup stream.stop()
async def test_update_stream_source(hass): """Tests that the worker is re-invoked when the stream source is updated.""" worker_open = threading.Event() worker_wake = threading.Event() stream = Stream(hass, STREAM_SOURCE, {}) stream.add_provider(HLS_PROVIDER) # Note that retries are disabled by default in tests, however the stream is "restarted" when # the stream source is updated. py_av = MockPyAv() py_av.container.packets = PacketSequence(TEST_SEQUENCE_LENGTH) last_stream_source = None def blocking_open(stream_source, *args, **kwargs): nonlocal last_stream_source if not isinstance(stream_source, io.BytesIO): last_stream_source = stream_source # Let test know the thread is running worker_open.set() # Block worker thread until test wakes up worker_wake.wait() return py_av.open(stream_source, args, kwargs) with patch("av.open", new=blocking_open): stream.start() assert worker_open.wait(TIMEOUT) assert last_stream_source == STREAM_SOURCE assert stream.available # Update the stream source, then the test wakes up the worker and assert # that it re-opens the new stream (the test again waits on thread_started) worker_open.clear() stream.update_source(STREAM_SOURCE + "-updated-source") worker_wake.set() assert worker_open.wait(TIMEOUT) assert last_stream_source == STREAM_SOURCE + "-updated-source" worker_wake.set() assert stream.available # Cleanup stream.stop()
async def test_update_stream_source(hass): """Tests that the worker is re-invoked when the stream source is updated.""" worker_open = threading.Event() worker_wake = threading.Event() stream = Stream(hass, STREAM_SOURCE) stream.add_provider(STREAM_OUTPUT_FORMAT) # Note that keepalive is not set here. The stream is "restarted" even though # it is not stopping due to failure. py_av = MockPyAv() py_av.container.packets = PacketSequence(TEST_SEQUENCE_LENGTH) last_stream_source = None def blocking_open(stream_source, *args, **kwargs): nonlocal last_stream_source if not isinstance(stream_source, io.BytesIO): last_stream_source = stream_source # Let test know the thread is running worker_open.set() # Block worker thread until test wakes up worker_wake.wait() return py_av.open(stream_source, args, kwargs) with patch("av.open", new=blocking_open): stream.start() assert worker_open.wait(TIMEOUT) assert last_stream_source == STREAM_SOURCE # Update the stream source, then the test wakes up the worker and assert # that it re-opens the new stream (the test again waits on thread_started) worker_open.clear() stream.update_source(STREAM_SOURCE + "-updated-source") worker_wake.set() assert worker_open.wait(TIMEOUT) assert last_stream_source == STREAM_SOURCE + "-updated-source" worker_wake.set() # Ccleanup stream.stop()