"""When an slskd download is abandoned (times out or errors), the enqueued transfers must be cancelled — otherwise, as the pipeline falls through to other peers for the same album, abandoned transfers pile up in slskd (many downloads of one album from different sources).""" import json import pytest import lyra_worker.adapters._slskd as slskd_mod from lyra_worker.adapters._slskd import SlskdClient class _Resp: def __init__(self, payload=None): self._p = payload if payload is not None else {} def raise_for_status(self): pass def json(self): return self._p class _FakeRequests: """Enqueue OK; polling always reports the file still in progress (never completes); records DELETEs so the test can assert the abandoned transfer was cancelled.""" def __init__(self, state="InProgress"): self.deleted = [] self._poll = {"directories": [{"files": [ {"filename": "f1.flac", "size": 5, "state": state, "id": "t1"}, ]}]} def post(self, url, **kw): return _Resp({}) def get(self, url, **kw): return _Resp(self._poll) def delete(self, url, **kw): self.deleted.append(url) return _Resp({}) def _client(tmp_path): return SlskdClient({"slskd.url": "http://x", "slskd.api_key": "k", "slskd.downloadsDir": str(tmp_path)}) _REF = json.dumps({"username": "peerA", "files": [{"filename": "f1.flac", "size": 5}]}) def test_cancels_transfer_on_timeout(tmp_path, monkeypatch): fake = _FakeRequests(state="InProgress") monkeypatch.setattr(slskd_mod, "requests", fake) monkeypatch.setattr(slskd_mod.time, "sleep", lambda _s: None) monkeypatch.setattr(slskd_mod, "_XFER_POLLS", 2) with pytest.raises(TimeoutError): _client(tmp_path).download(_REF, str(tmp_path / "dest"), lambda _p: None) assert any(u.endswith("/api/v0/transfers/downloads/peerA/t1") for u in fake.deleted), fake.deleted def test_cancels_transfer_on_error_state(tmp_path, monkeypatch): fake = _FakeRequests(state="Completed, Errored") monkeypatch.setattr(slskd_mod, "requests", fake) monkeypatch.setattr(slskd_mod.time, "sleep", lambda _s: None) monkeypatch.setattr(slskd_mod, "_XFER_POLLS", 5) with pytest.raises(RuntimeError): _client(tmp_path).download(_REF, str(tmp_path / "dest"), lambda _p: None) assert any(u.endswith("/peerA/t1") for u in fake.deleted), fake.deleted