Skip to content

Commit

Permalink
Dinkum listener compat fixes with tests (#154)
Browse files Browse the repository at this point in the history
  • Loading branch information
NeonDaniel authored May 20, 2023
1 parent e118d77 commit 48550a0
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 4 deletions.
6 changes: 6 additions & 0 deletions ovos_plugin_manager/templates/hotwords.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ def found_wake_word(self, frame_data):
"""
return False

def reset(self):
"""
Reset the WW engine to prepare for a new detection
"""
pass

def update(self, chunk):
"""Updates the hotword engine with new audio data.
Expand Down
8 changes: 4 additions & 4 deletions ovos_plugin_manager/templates/microphone.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@

@dataclass
class Microphone:
sample_rate: int
sample_width: int
sample_channels: int
chunk_size: int
sample_rate: int = 16000
sample_width: int = 2
sample_channels: int = 1
chunk_size: int = 4096

@property
def frames_per_chunk(self) -> int:
Expand Down
92 changes: 92 additions & 0 deletions test/unittests/templates/test_microphone_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import unittest
from unittest.mock import patch, Mock

_TEST_CONFIG = {
"microphone": {
"module": "dummy",
"dummy": {
"sample_width": 1,
"sample_channels": 1,
"chunk_size": 2048
},
"ovos-microphone-plugin-alsa": {
"sample_width": 2,
"sample_channels": 1,
"chunk_size": 4096
}
}
}


class TestMicrophoneTemplate(unittest.TestCase):
def test_microphone_init(self):
from ovos_plugin_manager.templates.microphone import Microphone
# Default
mic = Microphone()
self.assertIsInstance(mic, Microphone)
self.assertIsInstance(mic.sample_rate, int)
self.assertIsInstance(mic.sample_width, int)
self.assertIsInstance(mic.sample_channels, int)
self.assertIsInstance(mic.chunk_size, int)

# Partial override with kwargs
mic_2 = Microphone(**_TEST_CONFIG['microphone']['dummy'])
self.assertIsInstance(mic_2, Microphone)
self.assertIsInstance(mic_2.sample_rate, int)
self.assertEqual(mic_2.sample_width, 1)
self.assertEqual(mic_2.sample_channels, 1)
self.assertEqual(mic_2.chunk_size, 2048)

# Override positional params
mic_3 = Microphone(1, 2, 3, 4)
self.assertIsInstance(mic_3, Microphone)
self.assertEqual(mic_3.sample_rate, 1)
self.assertEqual(mic_3.sample_width, 2)
self.assertEqual(mic_3.sample_channels, 3)
self.assertEqual(mic_3.chunk_size, 4)

self.assertNotEquals(mic, mic_2)
self.assertNotEquals(mic, mic_3)

def test_properties(self):
from ovos_plugin_manager.templates.microphone import Microphone
mic = Microphone()
self.assertIsInstance(mic.frames_per_chunk, int)
self.assertGreaterEqual(mic.frames_per_chunk, 0)
self.assertIsInstance(mic.seconds_per_chunk, float)
self.assertGreaterEqual(mic.seconds_per_chunk, 0)

def test_methods(self):
from ovos_plugin_manager.templates.microphone import Microphone
# Test failure cases
mic = Microphone()
with self.assertRaises(NotImplementedError):
mic.start()
with self.assertRaises(NotImplementedError):
mic.read_chunk()
with self.assertRaises(NotImplementedError):
mic.stop()

mock_start = Mock()
mock_read = Mock(return_value=b'1234')
mock_stop = Mock()

class MockMic(Microphone):
def start(self):
mock_start()

def read_chunk(self):
return mock_read()

def stop(self):
mock_stop()

# Test mic
mic = MockMic()
mic.start()
mock_start.assert_called_once()
chunk = mic.read_chunk()
self.assertEqual(chunk, b'1234')
mock_read.assert_called_once()
mic.stop()
mock_stop.assert_called_once()
66 changes: 66 additions & 0 deletions test/unittests/test_microphone.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import unittest
from unittest.mock import patch, Mock
from copy import copy
from ovos_plugin_manager import PluginTypes

_TEST_CONFIG = {
"microphone": {
"module": "dummy",
"dummy": {
"sample_width": 1,
"sample_channels": 1,
"chunk_size": 2048
},
"ovos-microphone-plugin-alsa": {
"sample_width": 2,
"sample_channels": 1,
"chunk_size": 4096
}
}
}


class TestMicrophoneFactory(unittest.TestCase):
def test_create_microphone(self):
from ovos_plugin_manager.microphone import OVOSMicrophoneFactory
real_get_class = OVOSMicrophoneFactory.get_class
mock_class = Mock()
mock_get_class = Mock(return_value=mock_class)
OVOSMicrophoneFactory.get_class = mock_get_class

OVOSMicrophoneFactory.create(config=_TEST_CONFIG)
mock_get_class.assert_called_once_with(
{**_TEST_CONFIG['microphone']['dummy'], **{"module": "dummy"}})
mock_class.assert_called_once_with(_TEST_CONFIG['microphone']['dummy'])
OVOSMicrophoneFactory.get_class = real_get_class

@patch("ovos_plugin_manager.microphone.load_plugin")
def test_get_class(self, load_plugin):
mock = Mock()
load_plugin.return_value = mock
from ovos_plugin_manager.microphone import OVOSMicrophoneFactory
# Test valid module
module = OVOSMicrophoneFactory.get_class(_TEST_CONFIG)
load_plugin.assert_called_once_with("dummy",
PluginTypes.MIC)
self.assertEqual(mock, module)

def test_get_microphone_config(self):
from ovos_plugin_manager.microphone import get_microphone_config
config = copy(_TEST_CONFIG)
dummy_config = get_microphone_config(config)
self.assertEqual(dummy_config, {**_TEST_CONFIG['microphone']['dummy'],
**{'module': 'dummy',
'lang': 'en-us'}})
config = copy(_TEST_CONFIG)
config['microphone']['module'] = 'ovos-microphone-plugin-alsa'
alsa_config = get_microphone_config(config)
self.assertEqual(alsa_config,
{**_TEST_CONFIG['microphone']
['ovos-microphone-plugin-alsa'],
**{'module': 'ovos-microphone-plugin-alsa',
'lang': 'en-us'}})
config = copy(_TEST_CONFIG)
config['microphone']['module'] = 'fake'
fake_config = get_microphone_config(config)
self.assertEqual(fake_config, {'module': 'fake', 'lang': 'en-us'})

0 comments on commit 48550a0

Please sign in to comment.