283 lines
9.0 KiB
Python
283 lines
9.0 KiB
Python
# -*- Mode: Python; test-case-name: whipper.test.test_common_accurip -*-
|
|
# vi:si:et:sw=4:sts=4:ts=4
|
|
|
|
import sys
|
|
from io import StringIO
|
|
from os.path import dirname, join
|
|
from unittest import TestCase
|
|
from unittest.mock import MagicMock, patch
|
|
from urllib.error import HTTPError
|
|
|
|
from whipper.common.accurip import (
|
|
calculate_checksums, get_db_entry, print_report, verify_result,
|
|
_split_responses, EntryNotFound
|
|
)
|
|
from whipper.result.result import RipResult, TrackResult
|
|
|
|
|
|
class TestAccurateRipResponse(TestCase):
|
|
@patch(
|
|
"whipper.common.accurip.urlopen",
|
|
MagicMock(side_effect=HTTPError("", 404, "Not Found", None, None)),
|
|
)
|
|
def test_raises_entrynotfound_for_no_entry(self):
|
|
with self.assertRaises(EntryNotFound):
|
|
get_db_entry('definitely_a_404')
|
|
|
|
@patch(
|
|
"whipper.common.accurip.urlopen",
|
|
MagicMock(return_value=open(join(dirname(__file__), 'dBAR-002-0000f21c-00027ef8-05021002.bin'), 'rb')),
|
|
)
|
|
def test_AccurateRipResponse_parses_correctly(self):
|
|
responses = get_db_entry('c/1/2/dBAR-002-0000f21c-00027ef8-05021002.bin')
|
|
self.assertEqual(len(responses), 2)
|
|
|
|
self.assertEqual(responses[0].num_tracks, 2)
|
|
self.assertEqual(responses[0].discId1, '0000f21c')
|
|
self.assertEqual(responses[0].discId2, '00027ef8')
|
|
self.assertEqual(responses[0].cddbDiscId, '05021002')
|
|
self.assertEqual(responses[0].confidences[0], 12)
|
|
self.assertEqual(responses[0].confidences[1], 20)
|
|
self.assertEqual(responses[0].checksums[0], '284fc705')
|
|
self.assertEqual(responses[0].checksums[1], '9cc1f32e')
|
|
|
|
self.assertEqual(responses[1].num_tracks, 2)
|
|
self.assertEqual(responses[1].discId1, '0000f21c')
|
|
self.assertEqual(responses[1].discId2, '00027ef8')
|
|
self.assertEqual(responses[1].cddbDiscId, '05021002')
|
|
self.assertEqual(responses[1].confidences[0], 7)
|
|
self.assertEqual(responses[1].confidences[1], 7)
|
|
self.assertEqual(responses[1].checksums[0], 'dc77f9ab')
|
|
self.assertEqual(responses[1].checksums[1], 'dd97d2c3')
|
|
|
|
# XXX: test arc.py
|
|
|
|
|
|
class TestCalculateChecksums(TestCase):
|
|
def test_returns_none_for_bad_files(self):
|
|
self.assertEqual(
|
|
calculate_checksums(['/does/not/exist']),
|
|
{'v1': [None], 'v2': [None]}
|
|
)
|
|
|
|
# TODO: test success when file exists
|
|
|
|
|
|
class TestVerifyResult(TestCase):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
path = 'c/1/2/dBAR-002-0000f21c-00027ef8-05021002.bin'
|
|
with open(join(dirname(__file__), path[6:]), 'rb') as f:
|
|
cls.responses = _split_responses(f.read())
|
|
cls.checksums = {
|
|
'v1': ['284fc705', '9cc1f32e'],
|
|
'v2': ['dc77f9ab', 'dd97d2c3'],
|
|
}
|
|
|
|
def setUp(self):
|
|
self.result = RipResult()
|
|
for n in range(1, 2+1):
|
|
track = TrackResult()
|
|
track.number = n
|
|
self.result.tracks.append(track)
|
|
|
|
def test_empty_result_returns_false(self):
|
|
self.assertEqual(
|
|
verify_result(RipResult(), self.responses, self.checksums),
|
|
False
|
|
)
|
|
|
|
def test_empty_responses_returns_false(self):
|
|
self.assertEqual(
|
|
verify_result(self.result, [], self.checksums),
|
|
False
|
|
)
|
|
|
|
# XXX: would this happen?
|
|
def test_empty_checksums_returns_false(self):
|
|
self.assertEqual(
|
|
verify_result(self.result, self.responses, {}),
|
|
False
|
|
)
|
|
|
|
def test_wrong_checksums_returns_false(self):
|
|
self.assertEqual(
|
|
verify_result(self.result, self.responses, {
|
|
'v1': ['deadbeef', '89abcdef'],
|
|
'v2': ['76543210', '01234567']
|
|
}),
|
|
False
|
|
)
|
|
|
|
def test_incomplete_checksums(self):
|
|
self.assertEqual(
|
|
verify_result(self.result, self.responses, {
|
|
'v1': ['284fc705', '9cc1f32e'],
|
|
'v2': [None, 'dd97d2c3'],
|
|
}),
|
|
True
|
|
)
|
|
self.assertEqual(
|
|
verify_result(self.result, self.responses, {
|
|
'v1': ['284fc705', None],
|
|
'v2': ['dc77f9ab', 'dd97d2c3'],
|
|
}),
|
|
True
|
|
)
|
|
self.assertEqual(
|
|
verify_result(self.result, self.responses, {
|
|
'v1': ['284fc705', None],
|
|
'v2': [None, 'dd97d2c3'],
|
|
}),
|
|
True
|
|
)
|
|
|
|
def test_matches_only_v1_or_v2_responses(self):
|
|
self.assertEqual(
|
|
verify_result(
|
|
self.result, [self.responses[0]], self.checksums
|
|
),
|
|
True
|
|
)
|
|
self.assertEqual(
|
|
verify_result(
|
|
self.result, [self.responses[1]], self.checksums
|
|
),
|
|
True
|
|
)
|
|
|
|
def test_passes_with_htoa(self):
|
|
htoa = TrackResult()
|
|
htoa.number = 0
|
|
self.result.tracks.append(htoa)
|
|
self.assertEqual(
|
|
verify_result(self.result, self.responses, self.checksums),
|
|
True
|
|
)
|
|
|
|
def test_stores_accuraterip_results_on_result(self):
|
|
self.assertEqual(
|
|
verify_result(self.result, self.responses, self.checksums),
|
|
True
|
|
)
|
|
self.assertEqual(self.result.tracks[0].AR, {
|
|
'v1': {
|
|
'CRC': '284fc705',
|
|
'DBCRC': '284fc705',
|
|
'DBConfidence': 12,
|
|
},
|
|
'v2': {
|
|
'CRC': 'dc77f9ab',
|
|
'DBCRC': 'dc77f9ab',
|
|
'DBConfidence': 7
|
|
},
|
|
'DBMaxConfidence': 12,
|
|
'DBMaxConfidenceCRC': '284fc705',
|
|
})
|
|
self.assertEqual(self.result.tracks[1].AR, {
|
|
'v1': {
|
|
'CRC': '9cc1f32e',
|
|
'DBCRC': '9cc1f32e',
|
|
'DBConfidence': 20,
|
|
},
|
|
'v2': {
|
|
'CRC': 'dd97d2c3',
|
|
'DBCRC': 'dd97d2c3',
|
|
'DBConfidence': 7,
|
|
},
|
|
'DBMaxConfidence': 20,
|
|
'DBMaxConfidenceCRC': '9cc1f32e',
|
|
})
|
|
|
|
|
|
class TestAccurateRipReport(TestCase):
|
|
def setUp(self):
|
|
sys.stdout = StringIO()
|
|
self.result = RipResult()
|
|
track = TrackResult()
|
|
track.number = 1
|
|
track.AR = {
|
|
'v1': {
|
|
'CRC': '284fc705',
|
|
'DBCRC': '284fc705',
|
|
'DBConfidence': 12,
|
|
},
|
|
'v2': {
|
|
'CRC': 'dc77f9ab',
|
|
'DBCRC': 'dc77f9ab',
|
|
'DBConfidence': 4,
|
|
},
|
|
'DBMaxConfidence': 12,
|
|
'DBMaxConfidenceCRC': '284fc705',
|
|
}
|
|
self.result.tracks.append(track)
|
|
|
|
def tearDown(self):
|
|
sys.stdout = sys.__stdout__
|
|
|
|
def test_report_no_result(self):
|
|
track = TrackResult()
|
|
track.number = 1
|
|
self.result.tracks[0] = track
|
|
print_report(self.result)
|
|
self.assertEqual(
|
|
sys.stdout.getvalue(),
|
|
'track 1: unknown (error)\n'
|
|
)
|
|
|
|
def test_track_not_found(self):
|
|
self.result.tracks[0].AR['DBMaxConfidence'] = None
|
|
print_report(self.result)
|
|
self.assertEqual(
|
|
sys.stdout.getvalue(),
|
|
'track 1: rip NOT accurate (not found) '
|
|
' v1 [284fc705], v2 [dc77f9ab], DB [notfound]\n'
|
|
)
|
|
|
|
def test_htoa_not_tracked(self):
|
|
self.result.tracks[0].number = 0
|
|
self.result.tracks[0].AR['v1']['CRC'] = None
|
|
self.result.tracks[0].AR['v2']['CRC'] = None
|
|
print_report(self.result)
|
|
self.assertEqual(
|
|
sys.stdout.getvalue(),
|
|
'track 0: unknown (not tracked)\n'
|
|
)
|
|
|
|
def test_report_v1_only(self):
|
|
self.result.tracks[0].AR['v2']['DBCRC'] = None
|
|
self.result.tracks[0].AR['v2']['DBConfidence'] = None
|
|
print_report(self.result)
|
|
self.assertEqual(
|
|
sys.stdout.getvalue(),
|
|
'track 1: rip accurate (max confidence 12)'
|
|
' v1 [284fc705], v2 [dc77f9ab], DB [284fc705]\n'
|
|
)
|
|
|
|
def test_report_v2_only(self):
|
|
self.result.tracks[0].AR['v1']['DBCRC'] = None
|
|
self.result.tracks[0].AR['v1']['DBConfidence'] = None
|
|
print_report(self.result)
|
|
self.assertEqual(
|
|
sys.stdout.getvalue(),
|
|
'track 1: rip accurate (confidence 4 of 12)'
|
|
' v1 [284fc705], v2 [dc77f9ab], DB [dc77f9ab]\n'
|
|
)
|
|
|
|
def test_report_v1_and_v2_max_confidence(self):
|
|
print_report(self.result)
|
|
self.assertEqual(
|
|
sys.stdout.getvalue(),
|
|
'track 1: rip accurate (max confidence 12)'
|
|
' v1 [284fc705], v2 [dc77f9ab], DB [284fc705, dc77f9ab]\n'
|
|
)
|
|
|
|
def test_report_v1_and_v2(self):
|
|
self.result.tracks[0].AR['DBMaxConfidence'] = 66
|
|
print_report(self.result)
|
|
self.assertEqual(
|
|
sys.stdout.getvalue(),
|
|
'track 1: rip accurate (confidence 12 of 66)'
|
|
' v1 [284fc705], v2 [dc77f9ab], DB [284fc705, dc77f9ab]\n'
|
|
)
|