All checks were successful
Build RPi Pico firmware image / Build-Firmware (push) Successful in 3m21s
Check code formatting / Check-C-Format (push) Successful in 7s
Check code formatting / Check-Python-Flake8 (push) Successful in 9s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 4s
Run unit tests on host / Run-Unit-Tests (push) Successful in 8s
Run pytests / Check-Pytest (push) Successful in 11s
127 lines
4.2 KiB
Python
127 lines
4.2 KiB
Python
# SPDX-License-Identifier: MIT
|
|
# Copyright (c) 2025 Matthias Blankertz <matthias@blankertz.org>
|
|
|
|
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):
|
|
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 key
|
|
|
|
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 test_playlist_load():
|
|
contents = {b'foo/part': b'no',
|
|
b'foo/playlist/0': b'track1',
|
|
b'foo/playlist/1': 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/0': b'track1',
|
|
b'foo/playlist/1': 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/0': b'track1',
|
|
b'foo/playlist/1': 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/0': b'track1',
|
|
b'foo/playlist/1': 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/0': b'track1',
|
|
b'foo/playlist/1': b'track2',
|
|
b'foo/playlistpos': b'1'
|
|
})
|
|
uut = BTreeDB(contents)
|
|
assert uut.getPlaylistForTag(b'notfound') is None
|
|
|
|
|
|
def test_playlist_remains_lexicographically_ordered_by_key():
|
|
contents = FakeDB({b'foo/playlist/3': b'track3',
|
|
b'foo/playlist/2': b'track2',
|
|
b'foo/playlist/1': b'track1',
|
|
b'foo/playlistpos': b'1'
|
|
})
|
|
uut = BTreeDB(contents)
|
|
pl = uut.getPlaylistForTag(b'foo')
|
|
assert pl.getCurrentPath() == b'track1'
|
|
assert pl.getNextPath() == b'track2'
|
|
assert pl.getNextPath() == b'track3'
|
|
|
|
|
|
def test_playlist_remains_lexicographically_ordered_with_non_numeric_keys():
|
|
contents = FakeDB({b'foo/playlist/k': b'trackk',
|
|
b'foo/playlist/l': b'trackl',
|
|
b'foo/playlist/i': b'tracki',
|
|
b'foo/playlistpos': b'k'
|
|
})
|
|
uut = BTreeDB(contents)
|
|
pl = uut.getPlaylistForTag(b'foo')
|
|
assert pl.getCurrentPath() == b'trackk'
|
|
assert pl.getNextPath() == b'trackl'
|
|
assert pl.getNextPath() is None
|