Refactored cover art file tests into format specific test files

This commit is contained in:
Philipp Wolfer
2019-03-28 10:58:37 +01:00
parent 16506caf96
commit a268b13ceb
9 changed files with 206 additions and 320 deletions

View File

@@ -12,6 +12,7 @@ import picard.formats
from picard.formats import ext_to_format
from picard.metadata import Metadata
settings = {
'clear_existing_tags': False,
'embed_only_one_front_image': False,
@@ -141,12 +142,10 @@ def skipUnlessTestfile(func):
# prevent unittest to run tests in those classes
class CommonTests:
class SimpleFormatsTest(PicardTestCase):
class BaseFileTest(PicardTestCase):
testfile = None
testfile_ext = None
testfile_path = None
expected_info = None
def setUp(self):
super().setUp()
@@ -167,6 +166,10 @@ class CommonTests:
shutil.copy(filename, copy)
return copy
class SimpleFormatsTest(BaseFileTest):
expected_info = None
@skipUnlessTestfile
def test_can_open_and_save(self):
metadata = Metadata()

143
test/formats/coverart.py Normal file
View File

@@ -0,0 +1,143 @@
import os.path
from PyQt5 import QtCore
from picard import config
from picard.coverart.image import (
CoverArtImage,
TagCoverArtImage,
)
import picard.formats
from picard.metadata import Metadata
from .common import (
CommonTests,
skipUnlessTestfile,
)
def file_save_image(filename, image):
f = picard.formats.open_(filename)
metadata = Metadata()
metadata.images.append(image)
f._save(filename, metadata)
def load_coverart_file(filename):
with open(os.path.join('test', 'data', filename), 'rb') as f:
return f.read()
# prevent unittest to run tests in those classes
class CommonCoverArtTests:
class CoverArtTest(CommonTests.BaseFileTest):
supports_types = True
def setUp(self):
super().setUp()
self.jpegdata = load_coverart_file('mb.jpg')
self.pngdata = load_coverart_file('mb.png')
self.addCleanup(QtCore.QObject.tagger.run_cleanup)
@skipUnlessTestfile
def test_cover_art(self):
source_types = ["front", "booklet"]
# Use reasonable large data > 64kb.
# This checks a mutagen error with ASF files.
tests = [
CoverArtImage(data=self.jpegdata + b"a" * 1024 * 128, types=source_types),
CoverArtImage(data=self.pngdata + b"a" * 1024 * 128, types=source_types),
]
for test in tests:
file_save_image(self.filename, test)
f = picard.formats.open_(self.filename)
loaded_metadata = f._load(self.filename)
image = loaded_metadata.images[0]
self.assertEqual(test.mimetype, image.mimetype)
self.assertEqual(test, image)
def test_cover_art_with_types(self):
expected = set('abcdefg'[:]) if self.supports_types else set('a')
f = picard.formats.open_(self.filename)
f._save(self.filename, self._cover_metadata())
f = picard.formats.open_(self.filename)
loaded_metadata = f._load(self.filename)
found = set([chr(img.data[-1]) for img in loaded_metadata.images])
self.assertEqual(expected, found)
@skipUnlessTestfile
def test_cover_art_types_only_one_front(self):
config.setting['embed_only_one_front_image'] = True
f = picard.formats.open_(self.filename)
f._save(self.filename, self._cover_metadata())
f = picard.formats.open_(self.filename)
loaded_metadata = f._load(self.filename)
self.assertEqual(1, len(loaded_metadata.images))
self.assertEqual(ord('a'), loaded_metadata.images[0].data[-1])
def _cover_metadata(self):
imgdata = self.jpegdata
metadata = Metadata()
metadata.images.append(
TagCoverArtImage(
file='a',
tag='a',
data=imgdata + b'a',
support_types=True,
types=[u'booklet', u'front'],
)
)
metadata.images.append(
TagCoverArtImage(
file='b',
tag='b',
data=imgdata + b'b',
support_types=True,
types=[u'back'],
)
)
metadata.images.append(
TagCoverArtImage(
file='c',
tag='c',
data=imgdata + b'c',
support_types=True,
types=[u'front'],
)
)
metadata.images.append(
TagCoverArtImage(
file='d',
tag='d',
data=imgdata + b'd',
)
)
metadata.images.append(
TagCoverArtImage(
file='e',
tag='e',
data=imgdata + b'e',
is_front=False
)
)
metadata.images.append(
TagCoverArtImage(
file='f',
tag='f',
data=imgdata + b'f',
types=[u'front']
)
)
metadata.images.append(
TagCoverArtImage(
file='g',
tag='g',
data=imgdata + b'g',
types=[u'back'],
is_front=True
)
)
return metadata

View File

@@ -2,6 +2,7 @@ from .common import (
CommonTests,
load_metadata,
)
from .coverart import CommonCoverArtTests
class MonkeysAudioTest(CommonTests.TagFormatsTest):
@@ -76,3 +77,8 @@ class OptimFROGDUalStreamTest(CommonTests.TagFormatsTest):
def test_format(self):
metadata = load_metadata(self.filename)
self.assertEqual(metadata['~format'], 'OptimFROG DualStream Audio')
class ApeCoverArtTest(CommonCoverArtTests.CoverArtTest):
testfile = 'test.ape'
supports_types = False

View File

@@ -1,4 +1,5 @@
from .common import CommonTests
from .coverart import CommonCoverArtTests
class ASFTest(CommonTests.TagFormatsTest):
@@ -21,3 +22,11 @@ class WMATest(CommonTests.TagFormatsTest):
'~sample_rate': '44100',
'~bitrate': '64.0',
}
class AsfCoverArtTest(CommonCoverArtTests.CoverArtTest):
testfile = 'test.asf'
class WmaCoverArtTest(CommonCoverArtTests.CoverArtTest):
testfile = 'test.wma'

View File

@@ -1,315 +0,0 @@
import os.path
import shutil
from tempfile import mkstemp
from test.picardtestcase import PicardTestCase
from PyQt5 import QtCore
from picard import (
config,
# log,
)
from picard.coverart.image import (
CoverArtImage,
TagCoverArtImage,
)
import picard.formats
from picard.metadata import Metadata
from .common import (
load_raw,
settings,
)
class TestCoverArt(PicardTestCase):
def setUp(self):
super().setUp()
with open(os.path.join('test', 'data', 'mb.jpg'), 'rb') as f:
self.jpegdata = f.read()
with open(os.path.join('test', 'data', 'mb.png'), 'rb') as f:
self.pngdata = f.read()
def _common_set_up(self, extra=None):
config.setting = settings.copy()
if extra is not None:
config.setting.update(extra)
def _set_up(self, original, extra=None):
fd, self.filename = mkstemp(suffix=os.path.splitext(original)[1])
os.close(fd)
shutil.copy(original, self.filename)
self._common_set_up(extra)
def _common_tear_down(self):
QtCore.QObject.tagger.run_cleanup()
def _tear_down(self):
os.unlink(self.filename)
self._common_tear_down()
def test_coverartimage(self):
tests = {
'jpg': {
'mime': 'image/jpeg',
'data': self.jpegdata
},
'png': {
'mime': 'image/png',
'data': self.pngdata
},
}
tmp_files = []
for t in tests:
imgdata = tests[t]['data']
imgdata2 = imgdata + b'xxx'
# set data once
coverartimage = CoverArtImage(
data=imgdata2
)
tmp_file = coverartimage.tempfile_filename
tmp_files.append(tmp_file)
filesize = os.path.getsize(tmp_file)
# ensure file was written, and check its length
self.assertEqual(filesize, len(imgdata2))
self.assertEqual(coverartimage.data, imgdata2)
# set data again, with another payload
coverartimage.set_data(imgdata)
tmp_file = coverartimage.tempfile_filename
tmp_files.append(tmp_file)
filesize = os.path.getsize(tmp_file)
# check file length again
self.assertEqual(filesize, len(imgdata))
self.assertEqual(coverartimage.data, imgdata)
QtCore.QObject.tagger.run_cleanup()
def test_asf(self):
self._test_cover_art(os.path.join('test', 'data', 'test.wma'))
def test_ape(self):
self._test_cover_art(os.path.join('test', 'data', 'test.wv'))
def test_mp3(self):
self._test_cover_art(os.path.join('test', 'data', 'test.mp3'))
def test_mp4(self):
self._test_cover_art(os.path.join('test', 'data', 'test.m4a'))
def test_ogg(self):
self._test_cover_art(os.path.join('test', 'data', 'test.ogg'))
def test_flac(self):
self._test_cover_art(os.path.join('test', 'data', 'test.flac'))
# test for multiple images added to files, some types don't accept more than
# one, and there is no guarantee that order is preserved
def test_asf_types(self):
self._test_cover_art_types(os.path.join('test', 'data', 'test.wma'),
set('abcdefg'[:]))
def test_ape_types(self):
self._test_cover_art_types(os.path.join('test', 'data', 'test.wv'),
set('a'))
def test_mp3_types(self):
self._test_cover_art_types(os.path.join('test', 'data', 'test.mp3'),
set('abcdefg'[:]))
def test_mp4_types(self):
self._test_cover_art_types(os.path.join('test', 'data', 'test.m4a'),
set('abcdefg'[:]))
def test_ogg_types(self):
self._test_cover_art_types(os.path.join('test', 'data', 'test.ogg'),
set('abcdefg'[:]))
def test_flac_types(self):
self._test_cover_art_types(os.path.join('test', 'data', 'test.flac'),
set('abcdefg'[:]))
def test_asf_types_only_front(self):
self._test_cover_art_types_only_front(
os.path.join('test', 'data', 'test.wma'),
set('a'))
def test_ape_types_only_front(self):
self._test_cover_art_types_only_front(
os.path.join('test', 'data', 'test.wv'),
set('a'))
def test_mp3_types_only_front(self):
self._test_cover_art_types_only_front(
os.path.join('test', 'data', 'test.mp3'),
set('a'))
def test_mp4_types_only_front(self):
self._test_cover_art_types_only_front(
os.path.join('test', 'data', 'test.m4a'),
set('a'))
def test_ogg_types_only_front(self):
self._test_cover_art_types_only_front(
os.path.join('test', 'data', 'test.ogg'),
set('a'))
def test_flac_types_only_front(self):
self._test_cover_art_types_only_front(
os.path.join('test', 'data', 'test.flac'),
set('a'))
def test_flac_set_picture_dimensions(self):
self._set_up(os.path.join('test', 'data', 'test.flac'))
try:
tests = [
CoverArtImage(data=self.jpegdata),
CoverArtImage(data=self.pngdata),
]
for test in tests:
self._file_save_image(self.filename, test)
raw_metadata = load_raw(self.filename)
pic = raw_metadata.pictures[0]
self.assertNotEqual(pic.width, 0)
self.assertEqual(pic.width, test.width)
self.assertNotEqual(pic.height, 0)
self.assertEqual(pic.height, test.height)
finally:
self._tear_down()
def _test_cover_art(self, filename):
self._set_up(filename)
try:
source_types = ["front", "booklet"]
# Use reasonable large data > 64kb.
# This checks a mutagen error with ASF files.
tests = [
CoverArtImage(data=self.jpegdata + b"a" * 1024 * 128, types=source_types),
CoverArtImage(data=self.pngdata + b"a" * 1024 * 128, types=source_types),
]
for test in tests:
self._file_save_image(self.filename, test)
f = picard.formats.open_(self.filename)
loaded_metadata = f._load(self.filename)
image = loaded_metadata.images[0]
self.assertEqual(test.mimetype, image.mimetype)
self.assertEqual(test, image)
finally:
self._tear_down()
@staticmethod
def _file_save_image(filename, image):
f = picard.formats.open_(filename)
metadata = Metadata()
metadata.images.append(image)
f._save(filename, metadata)
def _cover_metadata(self):
imgdata = self.jpegdata
metadata = Metadata()
metadata.images.append(
TagCoverArtImage(
file='a',
tag='a',
data=imgdata + b'a',
support_types=True,
types=[u'booklet', u'front'],
)
)
metadata.images.append(
TagCoverArtImage(
file='b',
tag='b',
data=imgdata + b'b',
support_types=True,
types=[u'back'],
)
)
metadata.images.append(
TagCoverArtImage(
file='c',
tag='c',
data=imgdata + b'c',
support_types=True,
types=[u'front'],
)
)
metadata.images.append(
TagCoverArtImage(
file='d',
tag='d',
data=imgdata + b'd',
)
)
metadata.images.append(
TagCoverArtImage(
file='e',
tag='e',
data=imgdata + b'e',
is_front=False
)
)
metadata.images.append(
TagCoverArtImage(
file='f',
tag='f',
data=imgdata + b'f',
types=[u'front']
)
)
metadata.images.append(
TagCoverArtImage(
file='g',
tag='g',
data=imgdata + b'g',
types=[u'back'],
is_front=True
)
)
return metadata
def test_is_front_image(self):
self._common_set_up()
try:
m = self._cover_metadata()
front_images = set('acdfg'[:])
found = set()
for img in m.images:
if img.is_front_image():
found.add(img.tag)
self.assertEqual(front_images, found)
finally:
self._common_tear_down()
def _test_cover_art_types(self, filename, expect):
self._set_up(filename)
expect = {ord(char) for char in expect}
try:
f = picard.formats.open_(self.filename)
f._save(self.filename, self._cover_metadata())
f = picard.formats.open_(self.filename)
loaded_metadata = f._load(self.filename)
found = set()
for n, image in enumerate(loaded_metadata.images):
found.add(image.data[-1])
self.assertEqual(expect, found)
finally:
self._tear_down()
def _test_cover_art_types_only_front(self, filename, expect):
self._set_up(filename, {'embed_only_one_front_image': True})
expect = {ord(char) for char in expect}
try:
f = picard.formats.open_(self.filename)
f._save(self.filename, self._cover_metadata())
f = picard.formats.open_(self.filename)
loaded_metadata = f._load(self.filename)
found = set()
for n, image in enumerate(loaded_metadata.images):
found.add(image.data[-1])
self.assertEqual(expect, found)
finally:
self._tear_down()

View File

@@ -12,6 +12,7 @@ from .common import (
save_metadata,
skipUnlessTestfile,
)
from .coverart import CommonCoverArtTests
# prevent unittest to run tests in those classes
@@ -229,3 +230,7 @@ class AIFFTest(CommonId3Tests.Id3Test):
'~sample_rate': '44100',
'~bitrate': '1411.2',
}
class Mp3CoverArtTest(CommonCoverArtTests.CoverArtTest):
testfile = 'test.mp3'

View File

@@ -3,6 +3,7 @@ from .common import (
CommonTests,
load_metadata,
)
from .coverart import CommonCoverArtTests
class MP4Test(CommonTests.TagFormatsTest):
@@ -29,3 +30,7 @@ class MP4Test(CommonTests.TagFormatsTest):
def test_format(self):
metadata = load_metadata(self.filename)
self.assertIn('AAC LC', metadata['~format'])
class Mp4CoverArtTest(CommonCoverArtTests.CoverArtTest):
testfile = 'test.m4a'

View File

@@ -6,13 +6,19 @@ from picard import (
config,
log,
)
from picard.coverart.image import CoverArtImage
from picard.formats import vorbis
from .common import (
CommonTests,
load_metadata,
load_raw,
save_and_load_metadata,
skipUnlessTestfile,
)
from .coverart import (
CommonCoverArtTests,
file_save_image,
)
# prevent unittest to run tests in those classes
@@ -81,7 +87,7 @@ class VorbisUtilTest(PicardTestCase):
self.assertEqual(sanitized, ' }')
class FlacCoverArtTest(CommonCoverArtTests.CoverArtTestCase):
class FlacCoverArtTest(CommonCoverArtTests.CoverArtTest):
testfile = 'test.flac'
def test_set_picture_dimensions(self):
@@ -99,5 +105,5 @@ class FlacCoverArtTest(CommonCoverArtTests.CoverArtTestCase):
self.assertEqual(pic.height, test.height)
class OggCoverArtTest(CommonCoverArtTests.CoverArtTestCase):
class OggCoverArtTest(CommonCoverArtTests.CoverArtTest):
testfile = 'test.ogg'

View File

@@ -1,7 +1,10 @@
#!/usr/bin/env python
# coding: utf-8
import os.path
import unittest
from PyQt5 import QtCore
from test.picardtestcase import (
PicardTestCase,
create_fake_png,
@@ -84,6 +87,27 @@ class CoverArtImageTest(PicardTestCase):
self.assertEqual(image2, image3)
self.assertNotEqual(image2, image4)
def test_set_data(self):
self.addCleanup(QtCore.QObject.tagger.run_cleanup)
imgdata = data=create_fake_png(b'a')
imgdata2 = data=create_fake_png(b'xxx')
# set data once
coverartimage = CoverArtImage(data=imgdata2)
tmp_file = coverartimage.tempfile_filename
filesize = os.path.getsize(tmp_file)
# ensure file was written, and check its length
self.assertEqual(filesize, len(imgdata2))
self.assertEqual(coverartimage.data, imgdata2)
# set data again, with another payload
coverartimage.set_data(imgdata)
tmp_file = coverartimage.tempfile_filename
filesize = os.path.getsize(tmp_file)
# check file length again
self.assertEqual(filesize, len(imgdata))
self.assertEqual(coverartimage.data, imgdata)
class LocalFileCoverArtImageTest(PicardTestCase):
def test_set_file_url(self):