1
0
mirror of https://github.com/spl0k/supysonic.git synced 2024-12-22 08:56:17 +00:00
supysonic/tests/base/test_db.py

328 lines
11 KiB
Python
Raw Normal View History

2017-10-26 19:41:16 +00:00
# This file is part of Supysonic.
# Supysonic is a Python implementation of the Subsonic server API.
#
2023-01-14 15:45:44 +00:00
# Copyright (C) 2017-2023 Alban 'spl0k' Féron
2017-10-26 19:41:16 +00:00
#
# Distributed under terms of the GNU AGPLv3 license.
2017-12-14 21:28:49 +00:00
import re
2017-10-26 19:41:16 +00:00
import unittest
import uuid
2017-12-14 21:28:49 +00:00
from collections import namedtuple
2023-01-14 15:45:44 +00:00
from peewee import IntegrityError
2017-12-14 21:28:49 +00:00
2017-10-26 19:41:16 +00:00
from supysonic import db
2019-06-29 15:25:44 +00:00
date_regex = re.compile(r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$")
2017-10-26 19:41:16 +00:00
class DbTestCase(unittest.TestCase):
def setUp(self):
2019-06-29 15:25:44 +00:00
db.init_database("sqlite:")
2017-10-26 19:41:16 +00:00
def tearDown(self):
2017-12-19 22:16:55 +00:00
db.release_database()
2017-10-26 19:41:16 +00:00
def create_some_folders(self):
2022-12-10 14:14:37 +00:00
root_folder = db.Folder.create(root=True, name="Root folder", path="tests")
2017-12-14 21:28:49 +00:00
2022-12-10 14:14:37 +00:00
f1 = db.Folder.create(
2019-06-29 15:25:44 +00:00
root=False,
name="Child folder",
path="tests/assets",
cover_art="cover.jpg",
parent=root_folder,
2017-12-14 21:28:49 +00:00
)
2017-10-26 19:41:16 +00:00
2022-12-10 14:14:37 +00:00
f2 = db.Folder.create(
2019-06-29 15:25:44 +00:00
root=False,
name="Child folder (No Art)",
path="tests/formats",
parent=root_folder,
)
2022-12-10 14:14:37 +00:00
return root_folder, f1, f2
2017-10-26 19:41:16 +00:00
2019-06-29 15:25:44 +00:00
def create_some_tracks(self, artist=None, album=None):
root, child, child_2 = self.create_some_folders()
2017-10-26 21:16:20 +00:00
if not artist:
2022-12-10 14:14:37 +00:00
artist = db.Artist.create(name="Test artist")
2017-10-26 21:16:20 +00:00
if not album:
2022-12-10 14:14:37 +00:00
album = db.Album.create(artist=artist, name="Test Album")
2017-12-14 21:28:49 +00:00
2022-12-10 14:14:37 +00:00
track1 = db.Track.create(
2019-06-29 15:25:44 +00:00
title="Track Title",
album=album,
artist=artist,
disc=1,
number=1,
2024-09-08 18:38:35 +00:00
duration=3599,
2019-06-29 15:25:44 +00:00
has_art=True,
bitrate=320,
path="tests/assets/formats/silence.ogg",
last_modification=1234,
root_folder=root,
folder=child,
2017-12-14 21:28:49 +00:00
)
2022-12-10 14:14:37 +00:00
track2 = db.Track.create(
2019-06-29 15:25:44 +00:00
title="One Awesome Song",
album=album,
artist=artist,
disc=1,
number=2,
2024-09-08 18:38:35 +00:00
duration=3600,
2019-06-29 15:25:44 +00:00
bitrate=96,
path="tests/assets/23bytes",
last_modification=1234,
root_folder=root,
folder=child,
2017-12-14 21:28:49 +00:00
)
2017-10-26 21:16:20 +00:00
return track1, track2
2019-06-29 15:25:44 +00:00
def create_track_in(self, folder, root, artist=None, album=None, has_art=True):
2022-12-10 14:14:37 +00:00
artist = artist or db.Artist.create(name="Snazzy Artist")
album = album or db.Album.create(artist=artist, name="Rockin' Album")
return db.Track.create(
2019-06-29 15:25:44 +00:00
title="Nifty Number",
album=album,
artist=artist,
disc=1,
number=1,
duration=5,
has_art=has_art,
bitrate=96,
path="tests/assets/formats/silence.flac",
last_modification=1234,
root_folder=root,
folder=folder,
)
2019-06-29 15:25:44 +00:00
def create_user(self, name="Test User"):
2022-12-10 14:14:37 +00:00
return db.User.create(name=name, password="secret", salt="ABC+")
2017-12-14 21:28:49 +00:00
2017-10-27 19:42:36 +00:00
def create_playlist(self):
2022-12-10 14:14:37 +00:00
playlist = db.Playlist.create(user=self.create_user(), name="Playlist!")
2017-10-27 19:42:36 +00:00
return playlist
2023-01-14 15:45:44 +00:00
def test_ensure_sqlite_foreign_keys(self):
root, _, _ = self.create_some_folders()
self.assertRaises(IntegrityError, root.delete_instance)
2017-10-26 19:41:16 +00:00
def test_folder_base(self):
root_folder, child_folder, child_noart = self.create_some_folders()
track_embededart = self.create_track_in(child_noart, root_folder)
2017-10-26 19:41:16 +00:00
2019-06-29 15:25:44 +00:00
MockUser = namedtuple("User", ["id"])
2017-10-26 19:41:16 +00:00
user = MockUser(uuid.uuid4())
root = root_folder.as_subsonic_child(user)
self.assertIsInstance(root, dict)
2019-06-29 15:25:44 +00:00
self.assertIn("id", root)
self.assertIn("isDir", root)
self.assertIn("title", root)
self.assertIn("album", root)
self.assertIn("created", root)
self.assertTrue(root["isDir"])
self.assertEqual(root["title"], "Root folder")
self.assertEqual(root["album"], "Root folder")
self.assertRegex(root["created"], date_regex)
2017-10-26 19:41:16 +00:00
child = child_folder.as_subsonic_child(user)
2019-06-29 15:25:44 +00:00
self.assertIn("parent", child)
self.assertIn("artist", child)
self.assertIn("coverArt", child)
self.assertEqual(child["parent"], str(root_folder.id))
self.assertEqual(child["artist"], root_folder.name)
self.assertEqual(child["coverArt"], child["id"])
2017-12-14 21:28:49 +00:00
noart = child_noart.as_subsonic_child(user)
2019-06-29 15:25:44 +00:00
self.assertIn("coverArt", noart)
self.assertEqual(noart["coverArt"], str(track_embededart.id))
2017-10-26 19:41:16 +00:00
def test_folder_annotation(self):
root_folder, child_folder, _ = self.create_some_folders()
2017-10-26 19:41:16 +00:00
2017-12-14 21:28:49 +00:00
user = self.create_user()
2022-12-10 14:14:37 +00:00
db.StarredFolder.create(user=user, starred=root_folder)
db.RatingFolder.create(user=user, rated=root_folder, rating=2)
2019-06-29 15:25:44 +00:00
other = self.create_user("Other")
2022-12-10 14:14:37 +00:00
db.RatingFolder.create(user=other, rated=root_folder, rating=5)
2017-10-26 19:41:16 +00:00
root = root_folder.as_subsonic_child(user)
2019-06-29 15:25:44 +00:00
self.assertIn("starred", root)
self.assertIn("userRating", root)
self.assertIn("averageRating", root)
self.assertRegex(root["starred"], date_regex)
self.assertEqual(root["userRating"], 2)
self.assertEqual(root["averageRating"], 3.5)
2017-10-26 19:41:16 +00:00
child = child_folder.as_subsonic_child(user)
2019-06-29 15:25:44 +00:00
self.assertNotIn("starred", child)
self.assertNotIn("userRating", child)
2017-10-26 19:41:16 +00:00
2017-10-26 21:16:20 +00:00
def test_artist(self):
2022-12-10 14:14:37 +00:00
artist = db.Artist.create(name="Test Artist")
2017-10-26 21:16:20 +00:00
2017-12-14 21:28:49 +00:00
user = self.create_user()
2022-12-10 14:14:37 +00:00
db.StarredArtist.create(user=user, starred=artist)
2017-10-26 21:16:20 +00:00
artist_dict = artist.as_subsonic_artist(user)
self.assertIsInstance(artist_dict, dict)
2019-06-29 15:25:44 +00:00
self.assertIn("id", artist_dict)
self.assertIn("name", artist_dict)
self.assertIn("albumCount", artist_dict)
self.assertIn("starred", artist_dict)
self.assertEqual(artist_dict["name"], "Test Artist")
self.assertEqual(artist_dict["albumCount"], 0)
self.assertRegex(artist_dict["starred"], date_regex)
2017-12-14 21:28:49 +00:00
2022-12-10 14:14:37 +00:00
db.Album.create(name="Test Artist", artist=artist) # self-titled
db.Album.create(name="The Album After The First One", artist=artist)
2017-10-26 21:16:20 +00:00
artist_dict = artist.as_subsonic_artist(user)
2019-06-29 15:25:44 +00:00
self.assertEqual(artist_dict["albumCount"], 2)
2017-10-26 21:16:20 +00:00
def test_album(self):
2022-12-10 14:14:37 +00:00
artist = db.Artist.create(name="Test Artist")
album = db.Album.create(artist=artist, name="Test Album")
2017-12-14 21:28:49 +00:00
user = self.create_user()
2022-12-10 14:14:37 +00:00
db.StarredAlbum.create(user=user, starred=album)
2017-10-26 21:16:20 +00:00
root_folder, folder_art, folder_noart = self.create_some_folders()
2019-06-29 15:25:44 +00:00
track1 = self.create_track_in(
2019-10-01 14:55:23 +00:00
folder_noart, root_folder, artist=artist, album=album
2019-06-29 15:25:44 +00:00
)
2017-10-26 21:16:20 +00:00
album_dict = album.as_subsonic_album(user)
self.assertIsInstance(album_dict, dict)
2019-06-29 15:25:44 +00:00
self.assertIn("id", album_dict)
self.assertIn("name", album_dict)
self.assertIn("artist", album_dict)
self.assertIn("artistId", album_dict)
self.assertIn("songCount", album_dict)
self.assertIn("duration", album_dict)
self.assertIn("created", album_dict)
self.assertIn("starred", album_dict)
self.assertIn("coverArt", album_dict)
self.assertEqual(album_dict["name"], album.name)
self.assertEqual(album_dict["artist"], artist.name)
self.assertEqual(album_dict["artistId"], str(artist.id))
self.assertEqual(album_dict["songCount"], 1)
self.assertEqual(album_dict["duration"], 5)
self.assertEqual(album_dict["coverArt"], str(track1.id))
self.assertRegex(album_dict["created"], date_regex)
self.assertRegex(album_dict["starred"], date_regex)
2017-12-14 21:28:49 +00:00
2017-10-26 21:16:20 +00:00
def test_track(self):
track1, track2 = self.create_some_tracks()
2017-10-27 19:42:36 +00:00
2024-09-08 18:38:35 +00:00
assert track1.duration_str() == "59:59"
assert track2.duration_str() == "01:00:00"
2017-10-27 19:42:36 +00:00
# Assuming SQLite doesn't enforce foreign key constraints
2019-06-29 15:25:44 +00:00
MockUser = namedtuple("User", ["id"])
2017-10-27 19:42:36 +00:00
user = MockUser(uuid.uuid4())
track1_dict = track1.as_subsonic_child(user, None)
self.assertIsInstance(track1_dict, dict)
2019-06-29 15:25:44 +00:00
self.assertIn("id", track1_dict)
self.assertIn("parent", track1_dict)
self.assertIn("isDir", track1_dict)
self.assertIn("title", track1_dict)
self.assertFalse(track1_dict["isDir"])
self.assertIn("coverArt", track1_dict)
self.assertEqual(track1_dict["coverArt"], track1_dict["id"])
track2_dict = track2.as_subsonic_child(user, None)
2019-06-29 15:25:44 +00:00
self.assertEqual(track2_dict["coverArt"], track2_dict["parent"])
2017-10-27 19:42:36 +00:00
# ... we'll test the rest against the API XSD.
def test_user(self):
2017-12-14 21:28:49 +00:00
user = self.create_user()
2017-10-27 19:42:36 +00:00
user_dict = user.as_subsonic_user()
self.assertIsInstance(user_dict, dict)
def test_chat(self):
2017-12-14 21:28:49 +00:00
user = self.create_user()
2017-10-27 19:42:36 +00:00
2019-06-29 15:25:44 +00:00
line = db.ChatMessage(user=user, message="Hello world!")
2017-10-27 19:42:36 +00:00
line_dict = line.responsize()
self.assertIsInstance(line_dict, dict)
2019-06-29 15:25:44 +00:00
self.assertIn("username", line_dict)
self.assertEqual(line_dict["username"], user.name)
2017-10-27 19:42:36 +00:00
def test_playlist(self):
playlist = self.create_playlist()
playlist_dict = playlist.as_subsonic_playlist(playlist.user)
self.assertIsInstance(playlist_dict, dict)
def test_playlist_tracks(self):
playlist = self.create_playlist()
track1, track2 = self.create_some_tracks()
playlist.add(track1)
playlist.add(track2)
2019-06-29 15:25:44 +00:00
self.assertSequenceEqual(playlist.get_tracks(), [track1, track2])
2017-10-27 19:42:36 +00:00
playlist.add(track2.id)
playlist.add(track1.id)
2019-06-29 15:25:44 +00:00
self.assertSequenceEqual(
playlist.get_tracks(), [track1, track2, track2, track1]
)
2017-10-27 19:42:36 +00:00
playlist.clear()
self.assertSequenceEqual(playlist.get_tracks(), [])
playlist.add(str(track1.id))
2019-06-29 15:25:44 +00:00
self.assertSequenceEqual(playlist.get_tracks(), [track1])
2017-10-27 19:42:36 +00:00
2019-06-29 15:25:44 +00:00
self.assertRaises(ValueError, playlist.add, "some string")
2017-10-27 19:42:36 +00:00
self.assertRaises(NameError, playlist.add, 2345)
def test_playlist_remove_tracks(self):
playlist = self.create_playlist()
track1, track2 = self.create_some_tracks()
playlist.add(track1)
playlist.add(track2)
2019-06-29 15:25:44 +00:00
playlist.remove_at_indexes([0, 2])
self.assertSequenceEqual(playlist.get_tracks(), [track2])
2017-10-27 19:42:36 +00:00
playlist.add(track1)
playlist.add(track2)
playlist.add(track2)
2019-06-29 15:25:44 +00:00
playlist.remove_at_indexes([2, 1])
self.assertSequenceEqual(playlist.get_tracks(), [track2, track2])
2017-10-27 19:42:36 +00:00
playlist.add(track1)
2019-06-29 15:25:44 +00:00
playlist.remove_at_indexes([1, 1])
self.assertSequenceEqual(playlist.get_tracks(), [track2, track1])
2017-10-27 19:42:36 +00:00
def test_playlist_fixing(self):
playlist = self.create_playlist()
track1, track2 = self.create_some_tracks()
playlist.add(track1)
playlist.add(uuid.uuid4())
playlist.add(track2)
2019-06-29 15:25:44 +00:00
self.assertSequenceEqual(playlist.get_tracks(), [track1, track2])
2017-10-27 19:42:36 +00:00
2022-12-10 14:14:37 +00:00
track2.delete_instance()
2019-06-29 15:25:44 +00:00
self.assertSequenceEqual(playlist.get_tracks(), [track1])
2017-10-27 19:42:36 +00:00
2019-06-29 15:25:44 +00:00
playlist.tracks = "{0},{0},some random garbage,{0}".format(track1.id)
self.assertSequenceEqual(playlist.get_tracks(), [track1, track1, track1])
2017-10-26 21:16:20 +00:00
2019-06-29 15:25:44 +00:00
if __name__ == "__main__":
unittest.main()