From fd52a04535bfa1e25e6243df2f488cd4998b191a Mon Sep 17 00:00:00 2001 From: spl0k Date: Fri, 17 Nov 2017 19:56:14 +0100 Subject: [PATCH] Media retrieval (minus transcoding) tests --- tests/api/__init__.py | 2 + tests/api/test_media.py | 139 +++++++++++++++++++++++++++++++++++++++ tests/assets/23bytes | Bin 0 -> 23 bytes tests/assets/23bytes.txt | 1 + tests/assets/cover.jpg | Bin 0 -> 6155 bytes 5 files changed, 142 insertions(+) create mode 100644 tests/api/test_media.py create mode 100644 tests/assets/23bytes create mode 100644 tests/assets/23bytes.txt create mode 100644 tests/assets/cover.jpg diff --git a/tests/api/__init__.py b/tests/api/__init__.py index 681d5b4..909a20d 100644 --- a/tests/api/__init__.py +++ b/tests/api/__init__.py @@ -20,6 +20,7 @@ from .test_playlist import PlaylistTestCase from .test_browse import BrowseTestCase from .test_album_songs import AlbumSongsTestCase from .test_annotation import AnnotationTestCase +from .test_media import MediaTestCase def suite(): suite = unittest.TestSuite() @@ -34,6 +35,7 @@ def suite(): suite.addTest(unittest.makeSuite(BrowseTestCase)) suite.addTest(unittest.makeSuite(AlbumSongsTestCase)) suite.addTest(unittest.makeSuite(AnnotationTestCase)) + suite.addTest(unittest.makeSuite(MediaTestCase)) return suite diff --git a/tests/api/test_media.py b/tests/api/test_media.py new file mode 100644 index 0000000..12701f4 --- /dev/null +++ b/tests/api/test_media.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# vim:fenc=utf-8 +# +# 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 os.path +import uuid +from io import BytesIO +from PIL import Image + +from supysonic.db import Folder, Artist, Album, Track + +from .apitestbase import ApiTestBase + +class MediaTestCase(ApiTestBase): + def setUp(self): + super(MediaTestCase, self).setUp() + + self.folder = Folder() + self.folder.name = 'Root' + self.folder.path = os.path.abspath('tests/assets') + self.folder.root = True + self.folder.has_cover_art = True # 420x420 PNG + + artist = Artist() + artist.name = 'Artist' + + album = Album() + album.artist = artist + album.name = 'Album' + + self.track = Track() + self.track.title = '23bytes' + self.track.number = 1 + self.track.disc = 1 + self.track.artist = artist + self.track.album = album + self.track.path = os.path.abspath('tests/assets/23bytes') + self.track.root_folder = self.folder + self.track.folder = self.folder + self.track.duration = 2 + self.track.bitrate = 320 + self.track.content_type = 'audio/mpeg' + self.track.last_modification = 0 + + self.store.add(self.track) + self.store.commit() + + def test_stream(self): + self._make_request('stream', error = 10) + self._make_request('stream', { 'id': 'string' }, error = 0) + self._make_request('stream', { 'id': str(uuid.uuid4()) }, error = 70) + self._make_request('stream', { 'id': str(self.folder.id) }, error = 70) + self._make_request('stream', { 'id': str(self.track.id), 'maxBitRate': 'string' }, error = 0) + + rv = self.client.get('/rest/stream.view', query_string = { 'u': 'alice', 'p': 'Alic3', 'c': 'tests', 'id': str(self.track.id) }) + self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.mimetype, 'audio/mpeg') + self.assertEqual(len(rv.data), 23) + self.assertEqual(self.track.play_count, 1) + + # TODO test transcoding + + def test_download(self): + self._make_request('download', error = 10) + self._make_request('download', { 'id': 'string' }, error = 0) + self._make_request('download', { 'id': str(uuid.uuid4()) }, error = 70) + self._make_request('download', { 'id': str(self.folder.id) }, error = 70) + + rv = self.client.get('/rest/download.view', query_string = { 'u': 'alice', 'p': 'Alic3', 'c': 'tests', 'id': str(self.track.id) }) + self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.mimetype, 'audio/mpeg') + self.assertEqual(len(rv.data), 23) + self.assertEqual(self.track.play_count, 0) + + def test_get_cover_art(self): + self._make_request('getCoverArt', error = 10) + self._make_request('getCoverArt', { 'id': 'string' }, error = 0) + self._make_request('getCoverArt', { 'id': str(uuid.uuid4()) }, error = 70) + self._make_request('getCoverArt', { 'id': str(self.track.id) }, error = 70) + self._make_request('getCoverArt', { 'id': str(self.folder.id), 'size': 'large' }, error = 0) + + args = { 'u': 'alice', 'p': 'Alic3', 'c': 'tests', 'id': str(self.folder.id) } + rv = self.client.get('/rest/getCoverArt.view', query_string = args) + self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.mimetype, 'image/jpeg') + im = Image.open(BytesIO(rv.data)) + self.assertEqual(im.format, 'JPEG') + self.assertEqual(im.size, (420, 420)) + + args['size'] = 600 + rv = self.client.get('/rest/getCoverArt.view', query_string = args) + self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.mimetype, 'image/jpeg') + im = Image.open(BytesIO(rv.data)) + self.assertEqual(im.format, 'JPEG') + self.assertEqual(im.size, (420, 420)) + + self.skipTest("config dependant test, config isn't test proof") + args['size'] = 120 + rv = self.client.get('/rest/getCoverArt.view', query_string = args) + self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.mimetype, 'image/jpeg') + im = Image.open(BytesIO(rv.data)) + self.assertEqual(im.format, 'JPEG') + self.assertEqual(im.size, (120, 120)) + + # TODO test non square covers + + def test_get_lyrics(self): + self._make_request('getLyrics', error = 10) + self._make_request('getLyrics', { 'artist': 'artist' }, error = 10) + self._make_request('getLyrics', { 'title': 'title' }, error = 10) + + rv, child = self._make_request('getLyrics', { 'artist': 'some really long name hoping', 'title': 'to get absolutely no result' }, tag = 'lyrics') + self.assertIsNone(child.text) + + # ChartLyrics + rv, child = self._make_request('getLyrics', { 'artist': 'The Clash', 'title': 'London Calling' }, tag = 'lyrics') + self.assertIn('live by the river', child.text) + + self.skipTest('That weird logger/atexit error again') + # Local file + rv, child = self._make_request('getLyrics', { 'artist': 'artist', 'title': '23bytes' }, tag = 'lyrics') + self.assertIn('null', child.text) + print child + + def test_get_avatar(self): + self._make_request('getAvatar', error = 0) + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/assets/23bytes b/tests/assets/23bytes new file mode 100644 index 0000000000000000000000000000000000000000..3684b5c3682622274cac533e96fa1b0ae36b149f GIT binary patch literal 23 KcmZQzzzP5W7XSeO literal 0 HcmV?d00001 diff --git a/tests/assets/23bytes.txt b/tests/assets/23bytes.txt new file mode 100644 index 0000000..2870fb5 --- /dev/null +++ b/tests/assets/23bytes.txt @@ -0,0 +1 @@ +That's a file full of null bytes diff --git a/tests/assets/cover.jpg b/tests/assets/cover.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5dde98d591efeee1cea2e71f68dd6fa9f999eaba GIT binary patch literal 6155 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 bQA9H~(f-ao*J#$AJNmcf^JhJUDc%1E(_D3v literal 0 HcmV?d00001