async def test_record_stream(hass, hass_client):
    """
    Test record stream.

    Purposefully not mocking anything here to test full
    integration with the stream component.
    """
    await async_setup_component(hass, 'stream', {
        'stream': {}
    })

    with patch(
            'homeassistant.components.stream.recorder.recorder_save_worker'):
        # Setup demo track
        source = generate_h264_video()
        stream = preload_stream(hass, source)
        recorder = stream.add_provider('recorder')
        stream.start()

        segments = 0
        while True:
            segment = await recorder.recv()
            if not segment:
                break
            segments += 1

        stream.stop()

        assert segments == 3
Exemple #2
0
async def test_record_stream(hass, hass_client, stream_worker_sync,
                             record_worker_sync):
    """
    Test record stream.

    Tests full integration with the stream component, and captures the
    stream worker and save worker to allow for clean shutdown of background
    threads.  The actual save logic is tested in test_recorder_save below.
    """
    await async_setup_component(hass, "stream", {"stream": {}})

    stream_worker_sync.pause()

    # Setup demo track
    source = generate_h264_video()
    stream = preload_stream(hass, source)
    recorder = stream.add_provider("recorder")
    stream.start()

    while True:
        segment = await recorder.recv()
        if not segment:
            break
        segments = segment.sequence
        if segments > 1:
            stream_worker_sync.resume()

    stream.stop()
    assert segments > 1

    # Verify that the save worker was invoked, then block until its
    # thread completes and is shutdown completely to avoid thread leaks.
    record_worker_sync.join()
Exemple #3
0
async def test_has_keyframe(hass, record_worker_sync):
    """Test that the has_keyframe metadata matches the media."""
    await async_setup_component(hass, "stream", {"stream": {}})

    source = generate_h264_video()
    stream = create_stream(hass, source, {})

    # use record_worker_sync to grab output segments
    with patch.object(hass.config, "is_allowed_path", return_value=True):
        await stream.async_record("/example/path")

    # Our test video has keyframes every second. Use smaller parts so we have more
    # part boundaries to better test keyframe logic.
    with patch("homeassistant.components.stream.worker.TARGET_PART_DURATION",
               0.25):
        complete_segments = list(await record_worker_sync.get_segments())[:-1]
    assert len(complete_segments) >= 1

    # check that the Part has_keyframe metadata matches the keyframes in the media
    for segment in complete_segments:
        for part in segment.parts:
            av_part = av.open(io.BytesIO(segment.init + part.data))
            media_has_keyframe = any(
                packet.is_keyframe
                for packet in av_part.demux(av_part.streams.video[0]))
            av_part.close()
            assert part.has_keyframe == media_has_keyframe

    await record_worker_sync.join()

    stream.stop()
Exemple #4
0
async def test_stream_timeout(hass, hass_client):
    """Test hls stream timeout."""
    await async_setup_component(hass, 'stream', {'stream': {}})

    # Setup demo HLS track
    source = generate_h264_video()
    stream = preload_stream(hass, source)
    stream.add_provider('hls')

    # Request stream
    url = request_stream(hass, source)

    http_client = await hass_client()

    # Fetch playlist
    parsed_url = urlparse(url)
    playlist_response = await http_client.get(parsed_url.path)
    assert playlist_response.status == 200

    # Wait a minute
    future = dt_util.utcnow() + timedelta(minutes=1)
    async_fire_time_changed(hass, future)

    # Fetch again to reset timer
    playlist_response = await http_client.get(parsed_url.path)
    assert playlist_response.status == 200

    # Wait 5 minutes
    future = dt_util.utcnow() + timedelta(minutes=5)
    async_fire_time_changed(hass, future)

    # Ensure playlist not accessable
    fail_response = await http_client.get(parsed_url.path)
    assert fail_response.status == 404
Exemple #5
0
async def test_record_stream(hass, hass_client, record_worker_sync):
    """
    Test record stream.

    Tests full integration with the stream component, and captures the
    stream worker and save worker to allow for clean shutdown of background
    threads.  The actual save logic is tested in test_recorder_save below.
    """
    await async_setup_component(hass, "stream", {"stream": {}})

    # Setup demo track
    source = generate_h264_video()
    stream = create_stream(hass, source, {})
    with patch.object(hass.config, "is_allowed_path", return_value=True):
        await stream.async_record("/example/path")

    # After stream decoding finishes, the record worker thread starts
    segments = await record_worker_sync.get_segments()
    assert len(segments) >= 1

    # Verify that the save worker was invoked, then block until its
    # thread completes and is shutdown completely to avoid thread leaks.
    await record_worker_sync.join()

    stream.stop()
Exemple #6
0
async def test_recorder_timeout(hass, hass_client, stream_worker_sync):
    """
    Test recorder timeout.

    Mocks out the cleanup to assert that it is invoked after a timeout.
    This test does not start the recorder save thread.
    """
    await async_setup_component(hass, "stream", {"stream": {}})

    stream_worker_sync.pause()

    with patch("homeassistant.components.stream.IdleTimer.fire") as mock_timeout:
        # Setup demo track
        source = generate_h264_video()

        stream = create_stream(hass, source, {})
        with patch.object(hass.config, "is_allowed_path", return_value=True):
            await stream.async_record("/example/path")
        recorder = stream.add_provider(RECORDER_PROVIDER)

        await recorder.recv()

        # Wait a minute
        future = dt_util.utcnow() + timedelta(minutes=1)
        async_fire_time_changed(hass, future)
        await hass.async_block_till_done()

        assert mock_timeout.called

        stream_worker_sync.resume()
        stream.stop()
        await hass.async_block_till_done()
        await hass.async_block_till_done()
async def test_record_stream(hass, hass_client):
    """
    Test record stream.

    Purposefully not mocking anything here to test full
    integration with the stream component.
    """
    await async_setup_component(hass, "stream", {"stream": {}})

    with patch(
            "homeassistant.components.stream.recorder.recorder_save_worker"):
        # Setup demo track
        source = generate_h264_video()
        stream = preload_stream(hass, source)
        recorder = stream.add_provider("recorder")
        stream.start()

        segments = 0
        while True:
            segment = await recorder.recv()
            if not segment:
                break
            segments += 1

        stream.stop()

        assert segments > 1
Exemple #8
0
async def test_stream_ended(hass, stream_worker_sync):
    """Test hls stream packets ended."""
    await async_setup_component(hass, "stream", {"stream": {}})

    stream_worker_sync.pause()

    # Setup demo HLS track
    source = generate_h264_video()
    stream = preload_stream(hass, source)
    track = stream.add_provider("hls")

    # Request stream
    request_stream(hass, source)

    # Run it dead
    while True:
        segment = await track.recv()
        if segment is None:
            break
        segments = segment.sequence
        # Allow worker to finalize once enough of the stream is been consumed
        if segments > 1:
            stream_worker_sync.resume()

    assert segments > 1
    assert not track.get_segment()

    # Stop stream, if it hasn't quit already
    stream.stop()
Exemple #9
0
async def test_webocket_camera_stream(hass, hass_ws_client, hass_client,
                                      mock_camera, mock_stream):
    """Test camera/stream websocket command."""
    await async_setup_component(hass, 'camera')

    with patch('homeassistant.components.camera.request_stream',
               return_value='http://home.assistant/playlist.m3u8'
               ) as mock_request_stream, \
        patch('homeassistant.components.camera.demo.DemoCamera.stream_source',
              new_callable=PropertyMock) as mock_stream_source:
        mock_stream_source.return_value = generate_h264_video()
        # Request playlist through WebSocket
        client = await hass_ws_client(hass)
        await client.send_json({
            'id': 6,
            'type': 'camera/stream',
            'entity_id': 'camera.demo_camera',
        })
        msg = await client.receive_json()

        # Assert WebSocket response
        assert mock_request_stream.called
        assert msg['id'] == 6
        assert msg['type'] == TYPE_RESULT
        assert msg['success']
        assert msg['result']['url'][-13:] == 'playlist.m3u8'
Exemple #10
0
async def test_stream_ended(hass):
    """Test hls stream packets ended."""
    await async_setup_component(hass, 'stream', {
        'stream': {}
    })

    # Setup demo HLS track
    source = generate_h264_video()
    stream = preload_stream(hass, source)
    track = stream.add_provider('hls')
    track.num_segments = 2

    # Request stream
    request_stream(hass, source)

    # Run it dead
    segments = 0
    while await track.recv() is not None:
        segments += 1

    assert segments == 3
    assert not track.get_segment()

    # Stop stream, if it hasn't quit already
    stream.stop()
async def test_webocket_camera_stream(hass, hass_ws_client, hass_client,
                                      mock_camera, mock_stream):
    """Test camera/stream websocket command."""
    await async_setup_component(hass, 'camera')

    with patch('homeassistant.components.camera.request_stream',
               return_value='http://home.assistant/playlist.m3u8'
               ) as mock_request_stream, \
        patch('homeassistant.components.camera.demo.DemoCamera.stream_source',
              new_callable=PropertyMock) as mock_stream_source:
        mock_stream_source.return_value = generate_h264_video()
        # Request playlist through WebSocket
        client = await hass_ws_client(hass)
        await client.send_json({
            'id': 6,
            'type': 'camera/stream',
            'entity_id': 'camera.demo_camera',
        })
        msg = await client.receive_json()

        # Assert WebSocket response
        assert mock_request_stream.called
        assert msg['id'] == 6
        assert msg['type'] == TYPE_RESULT
        assert msg['success']
        assert msg['result']['url'][-13:] == 'playlist.m3u8'
Exemple #12
0
async def test_recorder_timeout(hass, hass_client, stream_worker_sync):
    """
    Test recorder timeout.

    Mocks out the cleanup to assert that it is invoked after a timeout.
    This test does not start the recorder save thread.
    """
    await async_setup_component(hass, "stream", {"stream": {}})

    stream_worker_sync.pause()

    with patch(
            "homeassistant.components.stream.recorder.RecorderOutput.cleanup"
    ) as mock_cleanup:
        # Setup demo track
        source = generate_h264_video()
        stream = preload_stream(hass, source)
        recorder = stream.add_provider("recorder")
        stream.start()

        await recorder.recv()

        # Wait a minute
        future = dt_util.utcnow() + timedelta(minutes=1)
        async_fire_time_changed(hass, future)
        await hass.async_block_till_done()

        assert mock_cleanup.called

        stream_worker_sync.resume()
        stream.stop()
        await hass.async_block_till_done()
        await hass.async_block_till_done()
async def test_record_path_not_allowed(hass, hass_client):
    """Test where the output path is not allowed by home assistant configuration."""
    await async_setup_component(hass, "stream", {"stream": {}})

    # Setup demo track
    source = generate_h264_video()
    stream = create_stream(hass, source)
    with patch.object(hass.config, "is_allowed_path",
                      return_value=False), pytest.raises(HomeAssistantError):
        await stream.async_record("/example/path")
Exemple #14
0
async def test_record_path_not_allowed(opp, opp_client):
    """Test where the output path is not allowed by open peer power configuration."""
    await async_setup_component(opp, "stream", {"stream": {}})

    # Setup demo track
    source = generate_h264_video()
    stream = create_stream(opp, source)
    with patch.object(opp.config, "is_allowed_path",
                      return_value=False), pytest.raises(OpenPeerPowerError):
        await stream.async_record("/example/path")
Exemple #15
0
async def test_recorder_discontinuity(tmpdir):
    """Test recorder save across a discontinuity."""
    # Setup
    source = generate_h264_video()
    filename = f"{tmpdir}/test.mp4"

    # Run
    recorder_save_worker(filename, [Segment(1, source, 4, 0), Segment(2, source, 4, 1)])

    # Assert
    assert os.path.exists(filename)
Exemple #16
0
async def test_recorder_save(tmpdir):
    """Test recorder save."""
    # Setup
    source = generate_h264_video()
    filename = f"{tmpdir}/test.mp4"

    # Run
    recorder_save_worker(filename, [Segment(1, source, 4)], "mp4")

    # Assert
    assert os.path.exists(filename)
Exemple #17
0
async def test_hls_stream(hass, hls_stream, stream_worker_sync):
    """
    Test hls stream.

    Purposefully not mocking anything here to test full
    integration with the stream component.
    """
    await async_setup_component(hass, "stream", {"stream": {}})

    stream_worker_sync.pause()

    # Setup demo HLS track
    source = generate_h264_video()
    stream = create_stream(hass, source, {})

    # Request stream
    stream.add_provider(HLS_PROVIDER)
    assert stream.available
    stream.start()

    hls_client = await hls_stream(stream)

    # Fetch master playlist
    master_playlist_response = await hls_client.get()
    assert master_playlist_response.status == HTTPStatus.OK

    # Fetch init
    master_playlist = await master_playlist_response.text()
    init_response = await hls_client.get("/init.mp4")
    assert init_response.status == HTTPStatus.OK

    # Fetch playlist
    playlist_url = "/" + master_playlist.splitlines()[-1]
    playlist_response = await hls_client.get(playlist_url)
    assert playlist_response.status == HTTPStatus.OK

    # Fetch segment
    playlist = await playlist_response.text()
    segment_url = "/" + [line for line in playlist.splitlines() if line][-1]
    segment_response = await hls_client.get(segment_url)
    assert segment_response.status == HTTPStatus.OK

    stream_worker_sync.resume()

    # The stream worker reported end of stream and exited
    assert not stream.available

    # Stop stream, if it hasn't quit already
    stream.stop()

    # Ensure playlist not accessible after stream ends
    fail_response = await hls_client.get()
    assert fail_response.status == HTTPStatus.NOT_FOUND
Exemple #18
0
async def test_recorder_save(tmpdir):
    """Test recorder save."""
    # Setup
    source = generate_h264_video()
    filename = f"{tmpdir}/test.mp4"

    # Run
    recorder_save_worker(
        filename, [Segment(1, *get_init_and_moof_data(source.getbuffer()), 4)])

    # Assert
    assert os.path.exists(filename)
async def test_recorder_save():
    """Test recorder save."""
    # Setup
    source = generate_h264_video()
    output = BytesIO()
    output.name = "test.mp4"

    # Run
    recorder_save_worker(output, [Segment(1, source, 4)])

    # Assert
    assert output.getvalue()
async def test_recorder_save():
    """Test recorder save."""
    # Setup
    source = generate_h264_video()
    output = BytesIO()
    output.name = 'test.mp4'

    # Run
    recorder_save_worker(output, [Segment(1, source, 4)])

    # Assert
    assert output.getvalue()
Exemple #21
0
async def test_record_stream_audio(
    hass, hass_client, stream_worker_sync, record_worker_sync
):
    """
    Test treatment of different audio inputs.

    Record stream output should have an audio channel when input has
    a valid codec and audio packets and no audio channel otherwise.
    """
    await async_setup_component(hass, "stream", {"stream": {}})

    # Generate source video with no audio
    source = generate_h264_video(container_format="mov")

    for a_codec, expected_audio_streams in (
        ("aac", 1),  # aac is a valid mp4 codec
        ("pcm_mulaw", 0),  # G.711 is not a valid mp4 codec
        ("empty", 0),  # audio stream with no packets
        (None, 0),  # no audio stream
    ):

        # Remux source video with new audio
        source = remux_with_audio(source, "mov", a_codec)  # mov can store PCM

        record_worker_sync.reset()
        stream_worker_sync.pause()

        stream = create_stream(hass, source, {})
        with patch.object(hass.config, "is_allowed_path", return_value=True):
            await stream.async_record("/example/path")
        recorder = stream.add_provider(RECORDER_PROVIDER)

        while True:
            await recorder.recv()
            if not (segment := recorder.last_segment):
                break
            last_segment = segment
            stream_worker_sync.resume()

        result = av.open(
            BytesIO(last_segment.init + last_segment.get_data()),
            "r",
            format="mp4",
        )

        assert len(result.streams.audio) == expected_audio_streams
        result.close()
        stream.stop()
        await hass.async_block_till_done()

        # Verify that the save worker was invoked, then block until its
        # thread completes and is shutdown completely to avoid thread leaks.
        await record_worker_sync.join()
Exemple #22
0
async def test_recorder_save(tmpdir):
    """Test recorder save."""
    # Setup
    source = generate_h264_video()
    filename = f"{tmpdir}/test.mp4"

    # Run
    segment = Segment(sequence=1)
    add_parts_to_segment(segment, source)
    segment.duration = 4
    recorder_save_worker(filename, [segment])

    # Assert
    assert os.path.exists(filename)
Exemple #23
0
async def test_durations(hass, record_worker_sync):
    """Test that the duration metadata matches the media."""
    await async_setup_component(
        hass,
        "stream",
        {
            "stream": {
                CONF_LL_HLS: True,
                CONF_SEGMENT_DURATION: SEGMENT_DURATION,
                CONF_PART_DURATION: TEST_PART_DURATION,
            }
        },
    )

    source = generate_h264_video()
    stream = create_stream(hass, source, {})

    # use record_worker_sync to grab output segments
    with patch.object(hass.config, "is_allowed_path", return_value=True):
        await stream.async_record("/example/path")

    complete_segments = list(await record_worker_sync.get_segments())[:-1]
    assert len(complete_segments) >= 1

    # check that the Part duration metadata matches the durations in the media
    running_metadata_duration = 0
    for segment in complete_segments:
        for part in segment.parts:
            av_part = av.open(io.BytesIO(segment.init + part.data))
            running_metadata_duration += part.duration
            # av_part.duration will just return the largest dts in av_part.
            # When we normalize by av.time_base this should equal the running duration
            assert math.isclose(
                running_metadata_duration,
                av_part.duration / av.time_base,
                abs_tol=1e-6,
            )
            av_part.close()
    # check that the Part durations are consistent with the Segment durations
    for segment in complete_segments:
        assert math.isclose(
            sum(part.duration for part in segment.parts),
            segment.duration,
            abs_tol=1e-6,
        )

    await record_worker_sync.join()

    stream.stop()
Exemple #24
0
async def test_hls_stream(hass, hass_client, stream_worker_sync):
    """
    Test hls stream.

    Purposefully not mocking anything here to test full
    integration with the stream component.
    """
    await async_setup_component(hass, "stream", {"stream": {}})

    stream_worker_sync.pause()

    # Setup demo HLS track
    source = generate_h264_video()
    stream = preload_stream(hass, source)
    stream.add_provider("hls")

    # Request stream
    url = request_stream(hass, source)

    http_client = await hass_client()

    # Fetch playlist
    parsed_url = urlparse(url)
    playlist_response = await http_client.get(parsed_url.path)
    assert playlist_response.status == 200

    # Fetch init
    playlist = await playlist_response.text()
    playlist_url = "/".join(parsed_url.path.split("/")[:-1])
    init_url = playlist_url + "/init.mp4"
    init_response = await http_client.get(init_url)
    assert init_response.status == 200

    # Fetch segment
    playlist = await playlist_response.text()
    playlist_url = "/".join(parsed_url.path.split("/")[:-1])
    segment_url = playlist_url + "/" + playlist.splitlines()[-1]
    segment_response = await http_client.get(segment_url)
    assert segment_response.status == 200

    stream_worker_sync.resume()

    # Stop stream, if it hasn't quit already
    stream.stop()

    # Ensure playlist not accessible after stream ends
    fail_response = await http_client.get(parsed_url.path)
    assert fail_response.status == HTTP_NOT_FOUND
Exemple #25
0
async def test_recorder_discontinuity(tmpdir):
    """Test recorder save across a discontinuity."""
    # Setup
    source = generate_h264_video()
    filename = f"{tmpdir}/test.mp4"

    # Run
    segment_1 = Segment(sequence=1, stream_id=0)
    add_parts_to_segment(segment_1, source)
    segment_1.duration = 4
    segment_2 = Segment(sequence=2, stream_id=1)
    add_parts_to_segment(segment_2, source)
    segment_2.duration = 4
    recorder_save_worker(filename, [segment_1, segment_2])
    # Assert
    assert os.path.exists(filename)
Exemple #26
0
async def test_recorder_discontinuity(tmpdir):
    """Test recorder save across a discontinuity."""
    # Setup
    source = generate_h264_video()
    filename = f"{tmpdir}/test.mp4"

    # Run
    init, moof_data = get_init_and_moof_data(source.getbuffer())
    recorder_save_worker(
        filename,
        [
            Segment(1, init, moof_data, 4, 0),
            Segment(2, init, moof_data, 4, 1),
        ],
    )

    # Assert
    assert os.path.exists(filename)
Exemple #27
0
async def test_record_lookback(opp, opp_client, stream_worker_sync,
                               record_worker_sync):
    """Exercise record with loopback."""
    await async_setup_component(opp, "stream", {"stream": {}})

    source = generate_h264_video()
    stream = create_stream(opp, source)

    # Start an HLS feed to enable lookback
    stream.add_provider("hls")
    stream.start()

    with patch.object(opp.config, "is_allowed_path", return_value=True):
        await stream.async_record("/example/path", lookback=4)

    # This test does not need recorder cleanup since it is not fully exercised

    stream.stop()
Exemple #28
0
async def test_handle_play_stream_service(hass, mock_camera, mock_stream):
    """Test camera play_stream service."""
    await async_setup_component(hass, 'media_player')
    data = {
        ATTR_ENTITY_ID: 'camera.demo_camera',
        camera.ATTR_MEDIA_PLAYER: 'media_player.test'
    }
    with patch('homeassistant.components.camera.request_stream'
               ) as mock_request_stream, \
        patch('homeassistant.components.camera.demo.DemoCamera.stream_source',
              new_callable=PropertyMock) as mock_stream_source:
        mock_stream_source.return_value = generate_h264_video()
        # Call service
        await hass.services.async_call(
            camera.DOMAIN, camera.SERVICE_PLAY_STREAM, data, blocking=True)
        # So long as we request the stream, the rest should be covered
        # by the play_media service tests.
        assert mock_request_stream.called
Exemple #29
0
async def test_hls_stream(opp, hls_stream, stream_worker_sync):
    """
    Test hls stream.

    Purposefully not mocking anything here to test full
    integration with the stream component.
    """
    await async_setup_component(opp, "stream", {"stream": {}})

    stream_worker_sync.pause()

    # Setup demo HLS track
    source = generate_h264_video()
    stream = create_stream(opp, source)

    # Request stream
    stream.add_provider("hls")
    stream.start()

    hls_client = await hls_stream(stream)

    # Fetch playlist
    playlist_response = await hls_client.get()
    assert playlist_response.status == 200

    # Fetch init
    playlist = await playlist_response.text()
    init_response = await hls_client.get("/init.mp4")
    assert init_response.status == 200

    # Fetch segment
    playlist = await playlist_response.text()
    segment_url = "/" + playlist.splitlines()[-1]
    segment_response = await hls_client.get(segment_url)
    assert segment_response.status == 200

    stream_worker_sync.resume()

    # Stop stream, if it hasn't quit already
    stream.stop()

    # Ensure playlist not accessible after stream ends
    fail_response = await hls_client.get()
    assert fail_response.status == HTTP_NOT_FOUND
Exemple #30
0
async def test_record_stream_audio(hass, hass_client, stream_worker_sync,
                                   record_worker_sync):
    """
    Test treatment of different audio inputs.

    Record stream output should have an audio channel when input has
    a valid codec and audio packets and no audio channel otherwise.
    """
    await async_setup_component(hass, "stream", {"stream": {}})

    for a_codec, expected_audio_streams in (
        ("aac", 1),  # aac is a valid mp4 codec
        ("pcm_mulaw", 0),  # G.711 is not a valid mp4 codec
        ("empty", 0),  # audio stream with no packets
        (None, 0),  # no audio stream
    ):
        record_worker_sync.reset()
        stream_worker_sync.pause()

        # Setup demo track
        source = generate_h264_video(container_format="mov",
                                     audio_codec=a_codec)  # mov can store PCM
        stream = preload_stream(hass, source)
        recorder = stream.add_provider("recorder")
        stream.start()

        while True:
            segment = await recorder.recv()
            if not segment:
                break
            last_segment = segment
            stream_worker_sync.resume()

        result = av.open(last_segment.segment, "r", format="mp4")

        assert len(result.streams.audio) == expected_audio_streams
        result.close()
        stream.stop()
        await hass.async_block_till_done()

        # Verify that the save worker was invoked, then block until its
        # thread completes and is shutdown completely to avoid thread leaks.
        record_worker_sync.join()
async def test_handle_play_stream_service(hass, mock_camera, mock_stream):
    """Test camera play_stream service."""
    await async_setup_component(hass, 'media_player')
    data = {
        ATTR_ENTITY_ID: 'camera.demo_camera',
        camera.ATTR_MEDIA_PLAYER: 'media_player.test'
    }
    with patch('homeassistant.components.camera.request_stream'
               ) as mock_request_stream, \
        patch('homeassistant.components.camera.demo.DemoCamera.stream_source',
              new_callable=PropertyMock) as mock_stream_source:
        mock_stream_source.return_value = generate_h264_video()
        # Call service
        await hass.services.async_call(camera.DOMAIN,
                                       camera.SERVICE_PLAY_STREAM,
                                       data,
                                       blocking=True)
        # So long as we request the stream, the rest should be covered
        # by the play_media service tests.
        assert mock_request_stream.called
Exemple #32
0
async def test_stream_timeout(hass, hass_client, stream_worker_sync):
    """Test hls stream timeout."""
    await async_setup_component(hass, "stream", {"stream": {}})

    stream_worker_sync.pause()

    # Setup demo HLS track
    source = generate_h264_video()
    stream = create_stream(hass, source, {})

    # Request stream
    stream.add_provider(HLS_PROVIDER)
    assert stream.available
    stream.start()
    url = stream.endpoint_url(HLS_PROVIDER)

    http_client = await hass_client()

    # Fetch playlist
    parsed_url = urlparse(url)
    playlist_response = await http_client.get(parsed_url.path)
    assert playlist_response.status == HTTPStatus.OK

    # Wait a minute
    future = dt_util.utcnow() + timedelta(minutes=1)
    async_fire_time_changed(hass, future)

    # Fetch again to reset timer
    playlist_response = await http_client.get(parsed_url.path)
    assert playlist_response.status == HTTPStatus.OK

    stream_worker_sync.resume()

    # Wait 5 minutes
    future = dt_util.utcnow() + timedelta(minutes=5)
    async_fire_time_changed(hass, future)
    await hass.async_block_till_done()

    # Ensure playlist not accessible
    fail_response = await http_client.get(parsed_url.path)
    assert fail_response.status == HTTPStatus.NOT_FOUND
Exemple #33
0
async def test_get_image(hass, filename):
    """Test that the has_keyframe metadata matches the media."""
    await async_setup_component(hass, "stream", {"stream": {}})

    source = generate_h264_video()

    # Since libjpeg-turbo is not installed on the CI runner, we use a mock
    with patch(
        "homeassistant.components.camera.img_util.TurboJPEGSingleton"
    ) as mock_turbo_jpeg_singleton:
        mock_turbo_jpeg_singleton.instance.return_value = mock_turbo_jpeg()
        stream = create_stream(hass, source, {})

    with patch.object(hass.config, "is_allowed_path", return_value=True):
        make_recording = hass.async_create_task(stream.async_record(filename))
        await make_recording
    assert stream._keyframe_converter._image is None

    assert await stream.async_get_image() == EMPTY_8_6_JPEG

    await stream.stop()
async def test_recorder_timeout(hass, hass_client):
    """Test recorder timeout."""
    await async_setup_component(hass, "stream", {"stream": {}})

    with patch(
            "homeassistant.components.stream.recorder.RecorderOutput.cleanup"
    ) as mock_cleanup:
        # Setup demo track
        source = generate_h264_video()
        stream = preload_stream(hass, source)
        recorder = stream.add_provider("recorder")
        stream.start()

        await recorder.recv()

        # Wait a minute
        future = dt_util.utcnow() + timedelta(minutes=1)
        async_fire_time_changed(hass, future)
        await hass.async_block_till_done()

        assert mock_cleanup.called
Exemple #35
0
async def test_hls_stream(hass, hass_client):
    """
    Test hls stream.

    Purposefully not mocking anything here to test full
    integration with the stream component.
    """
    await async_setup_component(hass, 'stream', {
        'stream': {}
    })

    # Setup demo HLS track
    source = generate_h264_video()
    stream = preload_stream(hass, source)
    stream.add_provider('hls')

    # Request stream
    url = request_stream(hass, source)

    http_client = await hass_client()

    # Fetch playlist
    parsed_url = urlparse(url)
    playlist_response = await http_client.get(parsed_url.path)
    assert playlist_response.status == 200

    # Fetch segment
    playlist = await playlist_response.text()
    playlist_url = '/'.join(parsed_url.path.split('/')[:-1])
    segment_url = playlist_url + playlist.splitlines()[-1][1:]
    segment_response = await http_client.get(segment_url)
    assert segment_response.status == 200

    # Stop stream, if it hasn't quit already
    stream.stop()

    # Ensure playlist not accessable after stream ends
    fail_response = await http_client.get(parsed_url.path)
    assert fail_response.status == 404
Exemple #36
0
async def test_stream_timeout_after_stop(opp, opp_client, stream_worker_sync):
    """Test hls stream timeout after the stream has been stopped already."""
    await async_setup_component(opp, "stream", {"stream": {}})

    stream_worker_sync.pause()

    # Setup demo HLS track
    source = generate_h264_video()
    stream = create_stream(opp, source)

    # Request stream
    stream.add_provider("hls")
    stream.start()

    stream_worker_sync.resume()
    stream.stop()

    # Wait 5 minutes and fire callback.  Stream should already have been
    # stopped so this is a no-op.
    future = dt_util.utcnow() + timedelta(minutes=5)
    async_fire_time_changed(opp, future)
    await opp.async_block_till_done()
async def test_recorder_timeout(hass, hass_client):
    """Test recorder timeout."""
    await async_setup_component(hass, 'stream', {
        'stream': {}
    })

    with patch(
            'homeassistant.components.stream.recorder.RecorderOutput.cleanup'
            ) as mock_cleanup:
        # Setup demo track
        source = generate_h264_video()
        stream = preload_stream(hass, source)
        recorder = stream.add_provider('recorder')
        stream.start()

        await recorder.recv()

        # Wait a minute
        future = dt_util.utcnow() + timedelta(minutes=1)
        async_fire_time_changed(hass, future)
        await hass.async_block_till_done()

        assert mock_cleanup.called
Exemple #38
0
async def test_stream_timeout(hass, hass_client):
    """Test hls stream timeout."""
    await async_setup_component(hass, 'stream', {
        'stream': {}
    })

    # Setup demo HLS track
    source = generate_h264_video()
    stream = preload_stream(hass, source)
    stream.add_provider('hls')

    # Request stream
    url = request_stream(hass, source)

    http_client = await hass_client()

    # Fetch playlist
    parsed_url = urlparse(url)
    playlist_response = await http_client.get(parsed_url.path)
    assert playlist_response.status == 200

    # Wait a minute
    future = dt_util.utcnow() + timedelta(minutes=1)
    async_fire_time_changed(hass, future)

    # Fetch again to reset timer
    playlist_response = await http_client.get(parsed_url.path)
    assert playlist_response.status == 200

    # Wait 5 minutes
    future = dt_util.utcnow() + timedelta(minutes=5)
    async_fire_time_changed(hass, future)

    # Ensure playlist not accessable
    fail_response = await http_client.get(parsed_url.path)
    assert fail_response.status == 404