/
/
/
1"""Test that two Deezer instances do not share authentication state."""
2
3from __future__ import annotations
4
5from unittest.mock import AsyncMock, Mock, patch
6
7from music_assistant.providers.deezer.gw_client import GWClient
8from music_assistant.providers.deezer.provider import SUPPORTED_FEATURES, DeezerProvider
9
10DEFAULT_FORMATS = [{"cipher": "BF_CBC_STRIPE", "format": "MP3_128"}]
11
12
13def _response(**cookies: str) -> Mock:
14 """Build a response carrying the given Set-Cookie values."""
15 return Mock(cookies={name: Mock(value=value) for name, value in cookies.items()})
16
17
18def _provider(instance_id: str, arl: str, mass: Mock) -> DeezerProvider:
19 manifest = Mock()
20 manifest.domain = "deezer"
21 config = Mock()
22 config.instance_id = instance_id
23 config.name = f"Deezer {instance_id}"
24 config.enabled = True
25 config.get_value.side_effect = lambda key, default=None: {
26 "log_level": "GLOBAL",
27 "arl_token": arl,
28 }.get(key, default)
29 return DeezerProvider(mass, manifest, config, SUPPORTED_FEATURES)
30
31
32async def test_clients_use_the_shared_session() -> None:
33 """Both clients run on the server-wide session, no provider owned one."""
34 mass = Mock()
35 mass.config.get.return_value = {}
36 provider = _provider("deezer--first", "arl-one", mass)
37
38 with (
39 patch("music_assistant.providers.deezer.provider.DeezerGQLClient") as gql_client,
40 patch("music_assistant.providers.deezer.provider.GWClient") as gw_client,
41 ):
42 gql_client.return_value.get_me = AsyncMock(return_value=Mock(id="user123"))
43 gw_client.return_value.setup = AsyncMock()
44 await provider.handle_async_init()
45
46 assert gql_client.call_args.kwargs["session"] is mass.http_session
47 assert gw_client.call_args.args[0] is mass.http_session
48
49
50def test_arl_is_sent_per_request() -> None:
51 """The arl travels with the request, it is never left in the shared jar."""
52 client = GWClient(Mock(), "arl-one")
53
54 assert client._request_cookies()["arl"] == "arl-one"
55
56
57def test_foreign_session_cookie_cannot_take_over() -> None:
58 """An empty sid is sent until deezer handed us one, so another instance cannot win."""
59 client = GWClient(Mock(), "arl-one")
60
61 assert client._request_cookies()["sid"] == ""
62
63 client._store_cookies(_response(sid="our-own-session"))
64 assert client._request_cookies()["sid"] == "our-own-session"
65
66
67def test_session_cookies_are_kept_per_instance() -> None:
68 """Two clients on one session must not see each other's sid."""
69 session = Mock()
70 one = GWClient(session, "arl-one")
71 two = GWClient(session, "arl-two")
72
73 one._store_cookies(_response(sid="session-one"))
74
75 assert one._request_cookies()["sid"] == "session-one"
76 assert two._request_cookies()["sid"] == ""
77
78
79def test_gw_client_formats_are_per_instance() -> None:
80 """Quality rights must not leak between instances through class-level state."""
81 one = GWClient(Mock(), "arl-one")
82 two = GWClient(Mock(), "arl-two")
83
84 one.formats.insert(0, {"cipher": "BF_CBC_STRIPE", "format": "FLAC"})
85 assert two.formats == DEFAULT_FORMATS
86 assert GWClient(Mock(), "arl-three").formats == DEFAULT_FORMATS
87