mycroft-core/test/unittests/tts/test_cache.py

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)