music-assistant-server

4.9 KBPY
test_streaming.py
4.9 KB140 lines • python
1"""Unit tests for KION Music streaming quality selection."""
2
3from __future__ import annotations
4
5from typing import TYPE_CHECKING, Any
6
7import pytest
8from music_assistant_models.enums import ContentType
9
10from music_assistant.providers.kion_music.constants import QUALITY_HIGH, QUALITY_LOSSLESS
11from music_assistant.providers.kion_music.streaming import KionMusicStreamingManager
12
13if TYPE_CHECKING:
14    from tests.providers.kion_music.conftest import (
15        StreamingProviderStub,
16        StreamingProviderStubWithTracking,
17    )
18
19
20def _make_download_info(
21    codec: str,
22    bitrate_in_kbps: int,
23    direct_link: str = "https://example.com/track",
24) -> Any:
25    """Build DownloadInfo-like object."""
26    return type(
27        "DownloadInfo",
28        (),
29        {
30            "codec": codec,
31            "bitrate_in_kbps": bitrate_in_kbps,
32            "direct_link": direct_link,
33        },
34    )()
35
36
37@pytest.fixture
38def streaming_manager(
39    streaming_provider_stub: StreamingProviderStub,
40) -> KionMusicStreamingManager:
41    """Create streaming manager with real stub (no Mock)."""
42    return KionMusicStreamingManager(streaming_provider_stub)  # type: ignore[arg-type]
43
44
45@pytest.fixture
46def streaming_manager_with_tracking(
47    streaming_provider_stub_with_tracking: StreamingProviderStubWithTracking,
48) -> KionMusicStreamingManager:
49    """Create streaming manager with tracking logger for assertions."""
50    return KionMusicStreamingManager(streaming_provider_stub_with_tracking)  # type: ignore[arg-type]
51
52
53def test_select_best_quality_lossless_returns_flac(
54    streaming_manager: KionMusicStreamingManager,
55) -> None:
56    """When preferred_quality is 'lossless' and list has MP3 and FLAC, FLAC is selected."""
57    mp3 = _make_download_info("mp3", 320, "https://example.com/track.mp3")
58    flac = _make_download_info("flac", 0, "https://example.com/track.flac")
59    download_infos = [mp3, flac]
60
61    result = streaming_manager._select_best_quality(download_infos, QUALITY_LOSSLESS)
62
63    assert result is not None
64    assert result.codec == "flac"
65    assert result.direct_link == "https://example.com/track.flac"
66
67
68def test_select_best_quality_high_returns_highest_bitrate(
69    streaming_manager: KionMusicStreamingManager,
70) -> None:
71    """When preferred is 'high' and list has MP3 and FLAC, highest bitrate is selected."""
72    mp3 = _make_download_info("mp3", 320, "https://example.com/track.mp3")
73    flac = _make_download_info("flac", 0, "https://example.com/track.flac")
74    download_infos = [mp3, flac]
75
76    result = streaming_manager._select_best_quality(download_infos, QUALITY_HIGH)
77
78    assert result is not None
79    assert result.codec == "mp3"
80    assert result.bitrate_in_kbps == 320
81
82
83def test_select_best_quality_label_lossless_flac_returns_flac(
84    streaming_manager: KionMusicStreamingManager,
85) -> None:
86    """When preferred_quality is UI label 'Lossless (FLAC)', FLAC is selected."""
87    mp3 = _make_download_info("mp3", 320, "https://example.com/track.mp3")
88    flac = _make_download_info("flac", 0, "https://example.com/track.flac")
89    download_infos = [mp3, flac]
90
91    result = streaming_manager._select_best_quality(download_infos, "Lossless (FLAC)")
92
93    assert result is not None
94    assert result.codec == "flac"
95
96
97def test_select_best_quality_lossless_no_flac_returns_fallback(
98    streaming_manager_with_tracking: KionMusicStreamingManager,
99) -> None:
100    """When lossless requested but no FLAC in list, returns best available (fallback)."""
101    mp3 = _make_download_info("mp3", 320, "https://example.com/track.mp3")
102    download_infos = [mp3]
103
104    result = streaming_manager_with_tracking._select_best_quality(download_infos, QUALITY_LOSSLESS)
105
106    assert result is not None
107    assert result.codec == "mp3"
108    assert streaming_manager_with_tracking.provider.logger._warning_count == 1  # type: ignore[attr-defined]
109
110
111def test_select_best_quality_empty_list_returns_none(
112    streaming_manager: KionMusicStreamingManager,
113) -> None:
114    """Empty download_infos returns None."""
115    result = streaming_manager._select_best_quality([], QUALITY_LOSSLESS)
116    assert result is None
117
118
119def test_select_best_quality_none_preferred_returns_highest_bitrate(
120    streaming_manager: KionMusicStreamingManager,
121) -> None:
122    """When preferred_quality is None, returns highest bitrate."""
123    mp3 = _make_download_info("mp3", 320, "https://example.com/track.mp3")
124    flac = _make_download_info("flac", 0, "https://example.com/track.flac")
125    download_infos = [mp3, flac]
126
127    result = streaming_manager._select_best_quality(download_infos, None)
128
129    assert result is not None
130    assert result.codec == "mp3"
131    assert result.bitrate_in_kbps == 320
132
133
134def test_get_content_type_flac_mp4_returns_flac(
135    streaming_manager: KionMusicStreamingManager,
136) -> None:
137    """flac-mp4 codec from get-file-info is mapped to ContentType.FLAC."""
138    assert streaming_manager._get_content_type("flac-mp4") == ContentType.FLAC
139    assert streaming_manager._get_content_type("FLAC-MP4") == ContentType.FLAC
140