172 lines
6.3 KiB
Python
172 lines
6.3 KiB
Python
"""Unit tests for the functionality in the TTS cache module."""
|
|
from pathlib import Path
|
|
from tempfile import mkdtemp
|
|
from unittest import TestCase
|
|
from unittest.mock import Mock, MagicMock, patch
|
|
|
|
from mycroft.tts.cache import hash_sentence, TextToSpeechCache
|
|
|
|
|
|
def _mock_mimic2_api():
|
|
response = MagicMock()
|
|
response.json = MagicMock()
|
|
response.json.return_value = dict(audio_base64=b'', visimes=None)
|
|
|
|
return response
|
|
|
|
|
|
class TestCache(TestCase):
|
|
def setUp(self) -> None:
|
|
self.cache_dir = Path(mkdtemp())
|
|
|
|
def tearDown(self) -> None:
|
|
for file_path in self.cache_dir.iterdir():
|
|
file_path.unlink()
|
|
self.cache_dir.rmdir()
|
|
|
|
def test_sentence_hash(self):
|
|
sentence = "This is a test sentence."
|
|
sentence_hash = hash_sentence(sentence)
|
|
self.assertEqual("4d6a0c4cf3f07eadd5ba147c67c6896f", sentence_hash)
|
|
|
|
@patch("mycroft.tts.cache.requests.get")
|
|
def test_persistent_cache(self, requests_mock):
|
|
preloaded_file_path = self._write_preloaded_file()
|
|
before_modified_time = preloaded_file_path.stat().st_mtime
|
|
requests_mock.return_value = _mock_mimic2_api()
|
|
tts_config = dict(preloaded_cache=self.cache_dir, url="testurl")
|
|
tts_cache = self._load_persistent_cache(tts_config)
|
|
actual_file_names = [path.name for path in self.cache_dir.iterdir()]
|
|
|
|
self.assertEqual(3, len(actual_file_names))
|
|
expected_file_names = [
|
|
"92ee7866d8154bb2cbf6fb49504e49fc.wav",
|
|
"70a73739cdebeffed0a6c692908c4c1f.wav",
|
|
"ed110791065a474b0fa00098450da19b.wav"
|
|
]
|
|
for file_name in expected_file_names:
|
|
self.assertIn(file_name, actual_file_names)
|
|
sentence_hash = file_name.split(".")[0]
|
|
self.assertIn(sentence_hash, tts_cache.cached_sentences.keys())
|
|
|
|
# Any pre-loaded cache files should not be overlaid
|
|
after_modified_time = preloaded_file_path.stat().st_mtime
|
|
self.assertEqual(before_modified_time, after_modified_time)
|
|
|
|
def test_no_persistent_cache(self):
|
|
tts_config = dict(url="testurl")
|
|
tts_cache = self._load_persistent_cache(tts_config)
|
|
actual_file_names = [path.name for path in self.cache_dir.iterdir()]
|
|
|
|
self.assertEqual(0, len(actual_file_names))
|
|
self.assertEqual(0, len(tts_cache.cached_sentences))
|
|
|
|
def _write_preloaded_file(self):
|
|
preloaded_file_name = "92ee7866d8154bb2cbf6fb49504e49fc.wav"
|
|
preloaded_file_path = self.cache_dir.joinpath(preloaded_file_name)
|
|
with open(preloaded_file_path, 'w') as test_file:
|
|
test_file.write("This is sentence one.")
|
|
|
|
return preloaded_file_path
|
|
|
|
def _load_persistent_cache(self, tts_config):
|
|
test_resource_directory = Path(__file__).parent.parent.joinpath("res")
|
|
tts_cache = TextToSpeechCache(
|
|
tts_config=tts_config,
|
|
tts_name="Test",
|
|
audio_file_type="wav"
|
|
)
|
|
tts_cache.resource_dir = test_resource_directory
|
|
tts_cache.load_persistent_cache()
|
|
|
|
return tts_cache
|
|
|
|
def test_clear_cache(self):
|
|
with open(self.cache_dir.joinpath('test.txt'), 'w') as test_file:
|
|
test_file.write("testing testing")
|
|
|
|
tts_cache = TextToSpeechCache(
|
|
tts_config=dict(preloaded_cache=self.cache_dir),
|
|
tts_name="Test",
|
|
audio_file_type="wav"
|
|
)
|
|
tts_cache.temporary_cache_dir = self.cache_dir
|
|
tts_cache.clear()
|
|
cache_contents = [path for path in self.cache_dir.iterdir()]
|
|
self.assertListEqual([], cache_contents)
|
|
|
|
@patch('mycroft.tts.cache.curate_cache')
|
|
def test_curate_cache(self, curate_mock):
|
|
tts_cache = TextToSpeechCache(
|
|
tts_config=dict(preloaded_cache=self.cache_dir),
|
|
tts_name="Test",
|
|
audio_file_type="wav"
|
|
)
|
|
# Setup content of sentence cache
|
|
files = {'kermit': tts_cache.define_audio_file('kermit'),
|
|
'fozzie': tts_cache.define_audio_file('fozzie'),
|
|
'gobo': tts_cache.define_audio_file('gobo')}
|
|
for sentence_hash, audio_file in files.items():
|
|
tts_cache.cached_sentences[sentence_hash] = (audio_file, None)
|
|
|
|
# Set curate_cache() to report that paths to kermit and gobo
|
|
# was removed
|
|
curate_mock.return_value = [files['kermit'].path,
|
|
files['gobo'].path]
|
|
tts_cache.curate()
|
|
curate_mock.assert_called_with(tts_cache.temporary_cache_dir,
|
|
min_free_percent=100)
|
|
|
|
# Verify that the "hashes" kermit and gobo was removed from the
|
|
# dict of hashes.
|
|
self.assertEqual(tts_cache.cached_sentences,
|
|
{'fozzie': (files['fozzie'], None)})
|
|
|
|
|
|
class MockFile(Mock):
|
|
def __init__(self, exists, *args, **kwargs):
|
|
super().__init__(args, kwargs)
|
|
self._exists = exists
|
|
|
|
def exists(self):
|
|
return self._exists
|
|
|
|
|
|
class TestCacheContains(TestCase):
|
|
"""Verify the `"X" in tts_cache` functionality."""
|
|
def setUp(self):
|
|
self.cache_dir = Path(mkdtemp())
|
|
self.tts_cache = TextToSpeechCache(
|
|
tts_config=dict(preloaded_cache=self.cache_dir),
|
|
tts_name="Test",
|
|
audio_file_type="wav"
|
|
)
|
|
files = {
|
|
'kermit': (MockFile(exists=True), MockFile(exists=True)),
|
|
'fozzie': (MockFile(exists=True), None),
|
|
'gobo': (MockFile(exists=False), None),
|
|
'piggy': (MockFile(exists=True), MockFile(exists=False))
|
|
}
|
|
for sentence_hash, (audio_file, phoneme_file) in files.items():
|
|
self.tts_cache.cached_sentences[sentence_hash] = (
|
|
audio_file, phoneme_file
|
|
)
|
|
|
|
def tearDown(self):
|
|
for file_path in self.cache_dir.iterdir():
|
|
file_path.unlink()
|
|
self.cache_dir.rmdir()
|
|
|
|
def test_hash_not_listed(self):
|
|
self.assertFalse('animal' in self.tts_cache)
|
|
|
|
def test_hash_exists_and_files_ok(self):
|
|
self.assertTrue('kermit' in self.tts_cache)
|
|
|
|
def test_only_audio_hash_exists_and_files_ok(self):
|
|
self.assertTrue('fozzie' in self.tts_cache)
|
|
|
|
def test_hash_exists_and_files_bad(self):
|
|
self.assertFalse('piggy' in self.tts_cache)
|
|
self.assertFalse('gobo' in self.tts_cache)
|