# SPDX-License-Identifier: MIT # Copyright (c) 2025 Matthias Blankertz import btree import pytest from utils import BTreeDB class FakeDB: def __init__(self, contents): self.contents = contents self.saved_contents = dict(contents) def flush(self): self.saved_contents = dict(self.contents) def values(self, start_key=None, end_key=None, flags=None): res = [] for key in sorted(self.contents): if start_key is not None and start_key > key: continue if end_key is not None and end_key <= key: break yield self.contents[key] res.append(self.contents[key]) def keys(self, start_key=None, end_key=None, flags=None): keys = [] if flags is not None and flags & btree.DESC != 0: start_key, end_key = end_key, start_key for key in sorted(self.contents): if start_key is not None and start_key > key: continue if end_key is not None and end_key <= key: break keys.append(key) if flags is not None and flags & btree.DESC != 0: keys.reverse() return iter(keys) def get(self, key, default=None): return self.contents.get(key, default) def __getitem__(self, key): return self.contents[key] def __setitem__(self, key, val): self.contents[key] = val def __delitem__(self, key): del self.contents[key] def __contains__(self, key): return key in self.contents def test_playlist_load(): contents = {b'foo/part': b'no', b'foo/playlist/00000': b'track1', b'foo/playlist/00001': b'track2', b'foo/playlisttt': b'no' } uut = BTreeDB(FakeDB(contents)) pl = uut.getPlaylistForTag(b'foo') assert list(pl.getPaths()) == [b'track1', b'track2'] assert pl.getCurrentPath() == b'track1' def test_playlist_nextpath(): contents = FakeDB({b'foo/part': b'no', b'foo/playlist/00000': b'track1', b'foo/playlist/00001': b'track2', b'foo/playlisttt': b'no' }) uut = BTreeDB(contents) pl = uut.getPlaylistForTag(b'foo') assert pl.getNextPath() == b'track2' assert contents.saved_contents[b'foo/playlistpos'] == b'1' def test_playlist_nextpath_last(): contents = FakeDB({b'foo/playlist/00000': b'track1', b'foo/playlist/00001': b'track2', b'foo/playlistpos': b'1' }) uut = BTreeDB(contents) pl = uut.getPlaylistForTag(b'foo') assert pl.getNextPath() is None assert contents.saved_contents[b'foo/playlistpos'] == b'0' def test_playlist_create(): contents = FakeDB({b'foo/playlist/00000': b'track1', b'foo/playlist/00001': b'track2', b'foo/playlistpos': b'1' }) newplaylist = [b'never gonna give you up.mp3', b'durch den monsun.mp3'] uut = BTreeDB(contents) new_pl = uut.createPlaylistForTag(b'foo', newplaylist) assert list(new_pl.getPaths()) == newplaylist assert new_pl.getCurrentPath() == newplaylist[0] assert uut.validate(True) def test_playlist_load_notexist(): contents = FakeDB({b'foo/playlist/00000': b'track1', b'foo/playlist/00001': b'track2', b'foo/playlistpos': b'1' }) uut = BTreeDB(contents) assert uut.getPlaylistForTag(b'notfound') is None def test_playlist_starts_at_beginning_in_persist_no_mode(): contents = FakeDB({b'foo/playlist/00000': b'track1', b'foo/playlist/00001': b'track2', b'foo/playlistpersist': b'no', }) uut = BTreeDB(contents) pl = uut.getPlaylistForTag(b'foo') assert pl.getCurrentPath() == b'track1' assert pl.getNextPath() == b'track2' del pl pl = uut.getPlaylistForTag(b'foo') assert pl.getCurrentPath() == b'track1' @pytest.mark.parametrize("mode", [b'no', b'track']) def test_playlist_ignores_offset_in_other_modes(mode): contents = FakeDB({b'foo/playlist/00000': b'track1', b'foo/playlist/00001': b'track2', b'foo/playlistpersist': mode, }) uut = BTreeDB(contents) pl = uut.getPlaylistForTag(b'foo') pl.setPlaybackOffset(42) del pl pl = uut.getPlaylistForTag(b'foo') assert pl.getPlaybackOffset() == 0 def test_playlist_stores_offset_in_offset_mode(): contents = FakeDB({b'foo/playlist/00000': b'track1', b'foo/playlist/00001': b'track2', b'foo/playlistpersist': b'offset', }) uut = BTreeDB(contents) pl = uut.getPlaylistForTag(b'foo') pl.setPlaybackOffset(42) del pl pl = uut.getPlaylistForTag(b'foo') assert pl.getPlaybackOffset() == 42 def test_playlist_resets_offset_on_next_track(): contents = FakeDB({b'foo/playlist/00000': b'track1', b'foo/playlist/00001': b'track2', b'foo/playlistpersist': b'offset', }) uut = BTreeDB(contents) pl = uut.getPlaylistForTag(b'foo') pl.setPlaybackOffset(42) assert pl.getNextPath() == b'track2' del pl pl = uut.getPlaylistForTag(b'foo') assert pl.getCurrentPath() == b'track2' assert pl.getPlaybackOffset() == 0