2017-11-10 23:13:18 +00:00
|
|
|
#!/usr/bin/env python
|
2018-03-04 20:49:56 +00:00
|
|
|
# coding: utf-8
|
2017-11-10 23:13:18 +00:00
|
|
|
#
|
|
|
|
# This file is part of Supysonic.
|
|
|
|
# Supysonic is a Python implementation of the Subsonic server API.
|
|
|
|
#
|
|
|
|
# Copyright (C) 2017 Alban 'spl0k' Féron
|
|
|
|
#
|
|
|
|
# Distributed under terms of the GNU AGPLv3 license.
|
|
|
|
|
|
|
|
import time
|
|
|
|
import uuid
|
|
|
|
|
2017-12-23 21:59:04 +00:00
|
|
|
from lxml import etree
|
2018-08-11 14:16:34 +00:00
|
|
|
from pony.orm import db_session
|
2017-12-23 21:59:04 +00:00
|
|
|
|
2018-08-11 14:16:34 +00:00
|
|
|
from supysonic.db import Folder, Artist, Album, Track
|
2017-11-10 23:13:18 +00:00
|
|
|
|
|
|
|
from .apitestbase import ApiTestBase
|
|
|
|
|
2019-06-29 15:25:44 +00:00
|
|
|
|
2017-11-10 23:13:18 +00:00
|
|
|
class BrowseTestCase(ApiTestBase):
|
|
|
|
def setUp(self):
|
|
|
|
super(BrowseTestCase, self).setUp()
|
|
|
|
|
2017-12-23 21:59:04 +00:00
|
|
|
with db_session:
|
2019-06-29 15:25:44 +00:00
|
|
|
Folder(root=True, name="Empty root", path="/tmp")
|
|
|
|
root = Folder(root=True, name="Root folder", path="tests/assets")
|
2017-12-23 21:59:04 +00:00
|
|
|
|
2019-06-29 15:25:44 +00:00
|
|
|
for letter in "ABC":
|
2017-12-23 21:59:04 +00:00
|
|
|
folder = Folder(
|
2019-06-29 15:25:44 +00:00
|
|
|
name=letter + "rtist",
|
|
|
|
path="tests/assets/{}rtist".format(letter),
|
|
|
|
parent=root,
|
2017-12-23 21:59:04 +00:00
|
|
|
)
|
|
|
|
|
2019-06-29 15:25:44 +00:00
|
|
|
artist = Artist(name=letter + "rtist")
|
2017-12-23 21:59:04 +00:00
|
|
|
|
2019-06-29 15:25:44 +00:00
|
|
|
for lether in "AB":
|
2017-12-23 21:59:04 +00:00
|
|
|
afolder = Folder(
|
2019-06-29 15:25:44 +00:00
|
|
|
name=letter + lether + "lbum",
|
|
|
|
path="tests/assets/{0}rtist/{0}{1}lbum".format(letter, lether),
|
|
|
|
parent=folder,
|
2017-12-23 21:59:04 +00:00
|
|
|
)
|
|
|
|
|
2019-06-29 15:25:44 +00:00
|
|
|
album = Album(name=letter + lether + "lbum", artist=artist)
|
2017-12-23 21:59:04 +00:00
|
|
|
|
2019-06-29 15:25:44 +00:00
|
|
|
for num, song in enumerate(["One", "Two", "Three"]):
|
2017-12-23 21:59:04 +00:00
|
|
|
track = Track(
|
2019-06-29 15:25:44 +00:00
|
|
|
disc=1,
|
|
|
|
number=num,
|
|
|
|
title=song,
|
|
|
|
duration=2,
|
|
|
|
album=album,
|
|
|
|
artist=artist,
|
|
|
|
bitrate=320,
|
|
|
|
path="tests/assets/{0}rtist/{0}{1}lbum/{2}".format(
|
|
|
|
letter, lether, song
|
|
|
|
),
|
|
|
|
last_modification=0,
|
|
|
|
root_folder=root,
|
|
|
|
folder=afolder,
|
2017-12-23 21:59:04 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
self.assertEqual(Folder.select().count(), 11)
|
|
|
|
self.assertEqual(Folder.select(lambda f: f.root).count(), 2)
|
|
|
|
self.assertEqual(Artist.select().count(), 3)
|
|
|
|
self.assertEqual(Album.select().count(), 6)
|
|
|
|
self.assertEqual(Track.select().count(), 18)
|
2017-11-10 23:13:18 +00:00
|
|
|
|
|
|
|
def test_get_music_folders(self):
|
|
|
|
# Do not validate against the XSD here, this is the only place where the API should return ids as ints
|
2017-12-23 21:59:04 +00:00
|
|
|
# all our ids are uuids :/
|
2019-06-29 15:25:44 +00:00
|
|
|
rv, child = self._make_request(
|
|
|
|
"getMusicFolders", tag="musicFolders", skip_xsd=True
|
|
|
|
)
|
2017-11-17 19:00:26 +00:00
|
|
|
self.assertEqual(len(child), 2)
|
2019-06-29 15:25:44 +00:00
|
|
|
self.assertSequenceEqual(
|
|
|
|
sorted(self._xpath(child, "./musicFolder/@name")),
|
|
|
|
["Empty root", "Root folder"],
|
|
|
|
)
|
2017-11-10 23:13:18 +00:00
|
|
|
|
|
|
|
def test_get_indexes(self):
|
2019-06-29 15:25:44 +00:00
|
|
|
self._make_request("getIndexes", {"musicFolderId": "abcdef"}, error=0)
|
2019-10-01 14:55:23 +00:00
|
|
|
self._make_request("getIndexes", {"musicFolderId": 1234567890}, error=70)
|
2019-06-29 15:25:44 +00:00
|
|
|
self._make_request("getIndexes", {"ifModifiedSince": "quoi"}, error=0)
|
|
|
|
|
|
|
|
rv, child = self._make_request(
|
|
|
|
"getIndexes",
|
|
|
|
{"ifModifiedSince": int(time.time() * 1000 + 1000)},
|
|
|
|
tag="indexes",
|
|
|
|
)
|
2017-11-10 23:13:18 +00:00
|
|
|
self.assertEqual(len(child), 0)
|
|
|
|
|
2017-12-23 21:59:04 +00:00
|
|
|
with db_session:
|
2019-06-29 15:25:44 +00:00
|
|
|
fid = Folder.get(name="Empty root").id
|
|
|
|
rv, child = self._make_request(
|
|
|
|
"getIndexes", {"musicFolderId": str(fid)}, tag="indexes"
|
|
|
|
)
|
2017-11-10 23:13:18 +00:00
|
|
|
self.assertEqual(len(child), 0)
|
|
|
|
|
2019-06-29 15:25:44 +00:00
|
|
|
rv, child = self._make_request("getIndexes", tag="indexes")
|
2017-11-10 23:13:18 +00:00
|
|
|
self.assertEqual(len(child), 3)
|
2019-06-29 15:25:44 +00:00
|
|
|
for i, letter in enumerate(["A", "B", "C"]):
|
|
|
|
self.assertEqual(child[i].get("name"), letter)
|
2017-11-10 23:13:18 +00:00
|
|
|
self.assertEqual(len(child[i]), 1)
|
2019-06-29 15:25:44 +00:00
|
|
|
self.assertEqual(child[i][0].get("name"), letter + "rtist")
|
2017-11-10 23:13:18 +00:00
|
|
|
|
|
|
|
def test_get_music_directory(self):
|
2019-06-29 15:25:44 +00:00
|
|
|
self._make_request("getMusicDirectory", error=10)
|
|
|
|
self._make_request("getMusicDirectory", {"id": "id"}, error=0)
|
2019-10-01 14:55:23 +00:00
|
|
|
self._make_request("getMusicDirectory", {"id": 1234567890}, error=70)
|
2017-11-10 23:13:18 +00:00
|
|
|
|
|
|
|
# should test with folders with both children folders and tracks. this code would break in that case
|
2017-12-23 21:59:04 +00:00
|
|
|
with db_session:
|
|
|
|
for f in Folder.select():
|
2019-06-29 15:25:44 +00:00
|
|
|
rv, child = self._make_request(
|
|
|
|
"getMusicDirectory", {"id": str(f.id)}, tag="directory"
|
|
|
|
)
|
|
|
|
self.assertEqual(child.get("id"), str(f.id))
|
|
|
|
self.assertEqual(child.get("name"), f.name)
|
2017-12-23 21:59:04 +00:00
|
|
|
self.assertEqual(len(child), f.children.count() + f.tracks.count())
|
2019-06-29 15:25:44 +00:00
|
|
|
for dbc, xmlc in zip(
|
|
|
|
sorted(f.children, key=lambda c: c.name),
|
|
|
|
sorted(child, key=lambda c: c.get("title")),
|
|
|
|
):
|
|
|
|
self.assertEqual(dbc.name, xmlc.get("title"))
|
|
|
|
self.assertEqual(xmlc.get("artist"), f.name)
|
|
|
|
self.assertEqual(xmlc.get("parent"), str(f.id))
|
|
|
|
for t, xmlc in zip(
|
|
|
|
sorted(f.tracks, key=lambda t: t.title),
|
|
|
|
sorted(child, key=lambda c: c.get("title")),
|
|
|
|
):
|
|
|
|
self.assertEqual(t.title, xmlc.get("title"))
|
|
|
|
self.assertEqual(xmlc.get("parent"), str(f.id))
|
2017-11-10 23:13:18 +00:00
|
|
|
|
|
|
|
def test_get_artists(self):
|
|
|
|
# same as getIndexes standard case
|
|
|
|
# dataset should be improved to have a different directory structure than /root/Artist/Album/Track
|
|
|
|
|
2019-06-29 15:25:44 +00:00
|
|
|
rv, child = self._make_request("getArtists", tag="artists")
|
2017-11-10 23:13:18 +00:00
|
|
|
self.assertEqual(len(child), 3)
|
2019-06-29 15:25:44 +00:00
|
|
|
for i, letter in enumerate(["A", "B", "C"]):
|
|
|
|
self.assertEqual(child[i].get("name"), letter)
|
2017-11-10 23:13:18 +00:00
|
|
|
self.assertEqual(len(child[i]), 1)
|
2019-06-29 15:25:44 +00:00
|
|
|
self.assertEqual(child[i][0].get("name"), letter + "rtist")
|
2017-11-10 23:13:18 +00:00
|
|
|
|
|
|
|
def test_get_artist(self):
|
|
|
|
# dataset should be improved to have tracks by a different artist than the album's artist
|
2019-06-29 15:25:44 +00:00
|
|
|
self._make_request("getArtist", error=10)
|
|
|
|
self._make_request("getArtist", {"id": "artist"}, error=0)
|
|
|
|
self._make_request("getArtist", {"id": str(uuid.uuid4())}, error=70)
|
2017-11-10 23:13:18 +00:00
|
|
|
|
2017-12-23 21:59:04 +00:00
|
|
|
with db_session:
|
|
|
|
for ar in Artist.select():
|
2019-06-29 15:25:44 +00:00
|
|
|
rv, child = self._make_request(
|
|
|
|
"getArtist", {"id": str(ar.id)}, tag="artist"
|
|
|
|
)
|
|
|
|
self.assertEqual(child.get("id"), str(ar.id))
|
|
|
|
self.assertEqual(child.get("albumCount"), str(len(child)))
|
2017-12-23 21:59:04 +00:00
|
|
|
self.assertEqual(len(child), ar.albums.count())
|
2019-06-29 15:25:44 +00:00
|
|
|
for dal, xal in zip(
|
|
|
|
sorted(ar.albums, key=lambda a: a.name),
|
|
|
|
sorted(child, key=lambda c: c.get("name")),
|
|
|
|
):
|
|
|
|
self.assertEqual(dal.name, xal.get("name"))
|
|
|
|
self.assertEqual(
|
|
|
|
xal.get("artist"), ar.name
|
|
|
|
) # could break with a better dataset
|
|
|
|
self.assertEqual(xal.get("artistId"), str(ar.id)) # see above
|
2017-11-10 23:13:18 +00:00
|
|
|
|
|
|
|
def test_get_album(self):
|
2019-06-29 15:25:44 +00:00
|
|
|
self._make_request("getAlbum", error=10)
|
|
|
|
self._make_request("getAlbum", {"id": "nastynasty"}, error=0)
|
|
|
|
self._make_request("getAlbum", {"id": str(uuid.uuid4())}, error=70)
|
2017-11-10 23:13:18 +00:00
|
|
|
|
2017-12-23 21:59:04 +00:00
|
|
|
with db_session:
|
|
|
|
a = Album.select().first()
|
2019-06-29 15:25:44 +00:00
|
|
|
rv, child = self._make_request("getAlbum", {"id": str(a.id)}, tag="album")
|
|
|
|
self.assertEqual(child.get("id"), str(a.id))
|
|
|
|
self.assertEqual(child.get("songCount"), str(len(child)))
|
2017-11-10 23:13:18 +00:00
|
|
|
|
2017-12-23 21:59:04 +00:00
|
|
|
self.assertEqual(len(child), a.tracks.count())
|
2019-06-29 15:25:44 +00:00
|
|
|
for dal, xal in zip(
|
|
|
|
sorted(a.tracks, key=lambda t: t.title),
|
|
|
|
sorted(child, key=lambda c: c.get("title")),
|
|
|
|
):
|
|
|
|
self.assertEqual(dal.title, xal.get("title"))
|
|
|
|
self.assertEqual(xal.get("album"), a.name)
|
|
|
|
self.assertEqual(xal.get("albumId"), str(a.id))
|
2017-11-10 23:13:18 +00:00
|
|
|
|
|
|
|
def test_get_song(self):
|
2019-06-29 15:25:44 +00:00
|
|
|
self._make_request("getSong", error=10)
|
|
|
|
self._make_request("getSong", {"id": "nastynasty"}, error=0)
|
|
|
|
self._make_request("getSong", {"id": str(uuid.uuid4())}, error=70)
|
2017-11-10 23:13:18 +00:00
|
|
|
|
2017-12-23 21:59:04 +00:00
|
|
|
with db_session:
|
|
|
|
s = Track.select().first()
|
2019-06-29 15:25:44 +00:00
|
|
|
self._make_request("getSong", {"id": str(s.id)}, tag="song")
|
2017-11-10 23:13:18 +00:00
|
|
|
|
|
|
|
def test_get_videos(self):
|
2019-06-29 15:25:44 +00:00
|
|
|
self._make_request("getVideos", error=0)
|
2017-11-10 23:13:18 +00:00
|
|
|
|
|
|
|
|
2019-06-29 15:25:44 +00:00
|
|
|
if __name__ == "__main__":
|
|
|
|
unittest.main()
|