mirror of
https://github.com/spl0k/supysonic.git
synced 2024-11-10 04:02:17 +00:00
330 lines
10 KiB
Python
330 lines
10 KiB
Python
#!/usr/bin/env python
|
|
# coding: utf-8
|
|
#
|
|
# This file is part of Supysonic.
|
|
# Supysonic is a Python implementation of the Subsonic server API.
|
|
#
|
|
# Copyright (C) 2017-2018 Alban 'spl0k' Féron
|
|
#
|
|
# Distributed under terms of the GNU AGPLv3 license.
|
|
|
|
import re
|
|
import unittest
|
|
import uuid
|
|
|
|
from collections import namedtuple
|
|
from pony.orm import db_session
|
|
|
|
from supysonic import db
|
|
|
|
date_regex = re.compile(r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$')
|
|
|
|
class DbTestCase(unittest.TestCase):
|
|
def setUp(self):
|
|
db.init_database('sqlite:', True)
|
|
|
|
try:
|
|
self.assertRegex
|
|
except AttributeError:
|
|
self.assertRegex = self.assertRegexpMatches
|
|
|
|
def tearDown(self):
|
|
db.release_database()
|
|
|
|
def create_some_folders(self):
|
|
root_folder = db.Folder(
|
|
root = True,
|
|
name = 'Root folder',
|
|
path = 'tests'
|
|
)
|
|
|
|
child_folder = db.Folder(
|
|
root = False,
|
|
name = 'Child folder',
|
|
path = 'tests/assets',
|
|
has_cover_art = True,
|
|
parent = root_folder
|
|
)
|
|
|
|
return root_folder, child_folder
|
|
|
|
def create_some_tracks(self, artist = None, album = None):
|
|
root, child = self.create_some_folders()
|
|
|
|
if not artist:
|
|
artist = db.Artist(name = 'Test artist')
|
|
|
|
if not album:
|
|
album = db.Album(artist = artist, name = 'Test Album')
|
|
|
|
track1 = db.Track(
|
|
title = 'Track Title',
|
|
album = album,
|
|
artist = artist,
|
|
disc = 1,
|
|
number = 1,
|
|
duration = 3,
|
|
bitrate = 320,
|
|
path = 'tests/assets/empty',
|
|
content_type = 'audio/mpeg',
|
|
last_modification = 1234,
|
|
root_folder = root,
|
|
folder = child
|
|
)
|
|
|
|
track2 = db.Track(
|
|
title = 'One Awesome Song',
|
|
album = album,
|
|
artist = artist,
|
|
disc = 1,
|
|
number = 2,
|
|
duration = 5,
|
|
bitrate = 96,
|
|
path = 'tests/assets/23bytes',
|
|
content_type = 'audio/mpeg',
|
|
last_modification = 1234,
|
|
root_folder = root,
|
|
folder = child
|
|
)
|
|
|
|
return track1, track2
|
|
|
|
def create_user(self, name = 'Test User'):
|
|
return db.User(
|
|
name = name,
|
|
password = 'secret',
|
|
salt = 'ABC+',
|
|
)
|
|
|
|
def create_playlist(self):
|
|
|
|
playlist = db.Playlist(
|
|
user = self.create_user(),
|
|
name = 'Playlist!'
|
|
)
|
|
|
|
return playlist
|
|
|
|
@db_session
|
|
def test_folder_base(self):
|
|
root_folder, child_folder = self.create_some_folders()
|
|
|
|
MockUser = namedtuple('User', [ 'id' ])
|
|
user = MockUser(uuid.uuid4())
|
|
|
|
root = root_folder.as_subsonic_child(user)
|
|
self.assertIsInstance(root, dict)
|
|
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)
|
|
|
|
child = child_folder.as_subsonic_child(user)
|
|
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'])
|
|
|
|
@db_session
|
|
def test_folder_annotation(self):
|
|
root_folder, child_folder = self.create_some_folders()
|
|
|
|
user = self.create_user()
|
|
star = db.StarredFolder(
|
|
user = user,
|
|
starred = root_folder
|
|
)
|
|
rating_user = db.RatingFolder(
|
|
user = user,
|
|
rated = root_folder,
|
|
rating = 2
|
|
)
|
|
other = self.create_user('Other')
|
|
rating_other = db.RatingFolder(
|
|
user = other,
|
|
rated = root_folder,
|
|
rating = 5
|
|
)
|
|
|
|
root = root_folder.as_subsonic_child(user)
|
|
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)
|
|
|
|
child = child_folder.as_subsonic_child(user)
|
|
self.assertNotIn('starred', child)
|
|
self.assertNotIn('userRating', child)
|
|
|
|
@db_session
|
|
def test_artist(self):
|
|
artist = db.Artist(name = 'Test Artist')
|
|
|
|
user = self.create_user()
|
|
star = db.StarredArtist(user = user, starred = artist)
|
|
|
|
artist_dict = artist.as_subsonic_artist(user)
|
|
self.assertIsInstance(artist_dict, dict)
|
|
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)
|
|
|
|
db.Album(name = 'Test Artist', artist = artist) # self-titled
|
|
db.Album(name = 'The Album After The First One', artist = artist)
|
|
|
|
artist_dict = artist.as_subsonic_artist(user)
|
|
self.assertEqual(artist_dict['albumCount'], 2)
|
|
|
|
@db_session
|
|
def test_album(self):
|
|
artist = db.Artist(name = 'Test Artist')
|
|
album = db.Album(artist = artist, name = 'Test Album')
|
|
|
|
user = self.create_user()
|
|
star = db.StarredAlbum(
|
|
user = user,
|
|
starred = album
|
|
)
|
|
|
|
# No tracks, shouldn't be stored under normal circumstances
|
|
self.assertRaises(ValueError, album.as_subsonic_album, user)
|
|
|
|
self.create_some_tracks(artist, album)
|
|
|
|
album_dict = album.as_subsonic_album(user)
|
|
self.assertIsInstance(album_dict, dict)
|
|
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.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'], 2)
|
|
self.assertEqual(album_dict['duration'], 8)
|
|
self.assertRegex(album_dict['created'], date_regex)
|
|
self.assertRegex(album_dict['starred'], date_regex)
|
|
|
|
@db_session
|
|
def test_track(self):
|
|
track1, track2 = self.create_some_tracks()
|
|
|
|
# Assuming SQLite doesn't enforce foreign key constraints
|
|
MockUser = namedtuple('User', [ 'id' ])
|
|
user = MockUser(uuid.uuid4())
|
|
|
|
track1_dict = track1.as_subsonic_child(user, None)
|
|
self.assertIsInstance(track1_dict, dict)
|
|
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'])
|
|
# ... we'll test the rest against the API XSD.
|
|
|
|
@db_session
|
|
def test_user(self):
|
|
user = self.create_user()
|
|
|
|
user_dict = user.as_subsonic_user()
|
|
self.assertIsInstance(user_dict, dict)
|
|
|
|
@db_session
|
|
def test_chat(self):
|
|
user = self.create_user()
|
|
|
|
line = db.ChatMessage(
|
|
user = user,
|
|
message = 'Hello world!'
|
|
)
|
|
|
|
line_dict = line.responsize()
|
|
self.assertIsInstance(line_dict, dict)
|
|
self.assertIn('username', line_dict)
|
|
self.assertEqual(line_dict['username'], user.name)
|
|
|
|
@db_session
|
|
def test_playlist(self):
|
|
playlist = self.create_playlist()
|
|
playlist_dict = playlist.as_subsonic_playlist(playlist.user)
|
|
self.assertIsInstance(playlist_dict, dict)
|
|
|
|
@db_session
|
|
def test_playlist_tracks(self):
|
|
playlist = self.create_playlist()
|
|
track1, track2 = self.create_some_tracks()
|
|
|
|
playlist.add(track1)
|
|
playlist.add(track2)
|
|
self.assertSequenceEqual(playlist.get_tracks(), [ track1, track2 ])
|
|
|
|
playlist.add(track2.id)
|
|
playlist.add(track1.id)
|
|
self.assertSequenceEqual(playlist.get_tracks(), [ track1, track2, track2, track1 ])
|
|
|
|
playlist.clear()
|
|
self.assertSequenceEqual(playlist.get_tracks(), [])
|
|
|
|
playlist.add(str(track1.id))
|
|
self.assertSequenceEqual(playlist.get_tracks(), [ track1 ])
|
|
|
|
self.assertRaises(ValueError, playlist.add, 'some string')
|
|
self.assertRaises(NameError, playlist.add, 2345)
|
|
|
|
@db_session
|
|
def test_playlist_remove_tracks(self):
|
|
playlist = self.create_playlist()
|
|
track1, track2 = self.create_some_tracks()
|
|
|
|
playlist.add(track1)
|
|
playlist.add(track2)
|
|
playlist.remove_at_indexes([ 0, 2 ])
|
|
self.assertSequenceEqual(playlist.get_tracks(), [ track2 ])
|
|
|
|
playlist.add(track1)
|
|
playlist.add(track2)
|
|
playlist.add(track2)
|
|
playlist.remove_at_indexes([ 2, 1 ])
|
|
self.assertSequenceEqual(playlist.get_tracks(), [ track2, track2 ])
|
|
|
|
playlist.add(track1)
|
|
playlist.remove_at_indexes([ 1, 1 ])
|
|
self.assertSequenceEqual(playlist.get_tracks(), [ track2, track1 ])
|
|
|
|
@db_session
|
|
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)
|
|
self.assertSequenceEqual(playlist.get_tracks(), [ track1, track2 ])
|
|
|
|
track2.delete()
|
|
self.assertSequenceEqual(playlist.get_tracks(), [ track1 ])
|
|
|
|
playlist.tracks = '{0},{0},some random garbage,{0}'.format(track1.id)
|
|
self.assertSequenceEqual(playlist.get_tracks(), [ track1, track1, track1 ])
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|
|
|