diff --git a/ovos_config/recommends/offline_male/fr-fr.conf b/ovos_config/recommends/offline_male/fr-fr.conf index 70c7dae..6ab02d9 100644 --- a/ovos_config/recommends/offline_male/fr-fr.conf +++ b/ovos_config/recommends/offline_male/fr-fr.conf @@ -1,6 +1,4 @@ { - - "tts": { "module": "ovos-tts-plugin-piper", "ovos-tts-plugin-piper": { diff --git a/ovos_config/recommends/offline_male/it-it.conf b/ovos_config/recommends/offline_male/it-it.conf index 026b5e6..975fdae 100644 --- a/ovos_config/recommends/offline_male/it-it.conf +++ b/ovos_config/recommends/offline_male/it-it.conf @@ -1,5 +1,4 @@ { - "tts": { "module": "ovos-tts-plugin-piper", "ovos-tts-plugin-piper": { diff --git a/ovos_config/recommends/offline_male/nl-nl.conf b/ovos_config/recommends/offline_male/nl-nl.conf index fd4ecd7..f627cec 100644 --- a/ovos_config/recommends/offline_male/nl-nl.conf +++ b/ovos_config/recommends/offline_male/nl-nl.conf @@ -1,5 +1,4 @@ { - "tts": { "module": "ovos-tts-plugin-piper", "ovos-tts-plugin-piper": { diff --git a/requirements/tests.txt b/requirements/tests.txt index 74a681e..8098d57 100644 --- a/requirements/tests.txt +++ b/requirements/tests.txt @@ -3,9 +3,4 @@ flake8==3.7.9 pytest==8.2.2 pytest-cov==2.8.1 cov-core==1.15.0 -sphinx==2.2.1 -sphinx-rtd-theme==0.4.3 -mock_msm~=0.9.2 -ovos-stt-plugin-vosk>=0.1.3 -python-vlc==1.1.2 -ovos-bus-client~=0.0.8 \ No newline at end of file +ovos-backend-client \ No newline at end of file diff --git a/test/unittests/configuration/__init__.py b/test/unittests/configuration/__init__.py new file mode 100644 index 0000000..b5d9e70 --- /dev/null +++ b/test/unittests/configuration/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2017 Mycroft AI Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# diff --git a/test/unittests/configuration/mycroft.conf b/test/unittests/configuration/mycroft.conf new file mode 100644 index 0000000..cbb649a --- /dev/null +++ b/test/unittests/configuration/mycroft.conf @@ -0,0 +1,9 @@ +{ + "lang": "pt-br", + "tts": { + "module": "espeak", + "espeak": { + "voice": "f1" + } + } +} diff --git a/test/unittests/configuration/mycroft.json b/test/unittests/configuration/mycroft.json new file mode 100644 index 0000000..f54fee2 --- /dev/null +++ b/test/unittests/configuration/mycroft.json @@ -0,0 +1,234 @@ +{ + "Audio": { + "backends": { + "OCP": { + "active": true, + "type": "ovos_common_play" + }, + "simple": { + "active": true, + "type": "ovos_audio_simple" + }, + "vlc": { + "active": true, + "type": "ovos_vlc" + } + }, + "default-backend": "OCP" + }, + "cache_path": "/tmp/mycroft/cache", + "confirm_listening": true, + "date_format": "MDY", + "debug": false, + "enclosure": { + "force_mycroft_ntp": true, + "ntp_sync_on_boot": false, + "platform": "PHAL" + }, + "gui": { + "extension": "generic", + "generic": { + "homescreen_supported": false + } + }, + "gui_websocket": { + "base_port": 18181, + "host": "0.0.0.0", + "route": "/gui", + "ssl": false + }, + "hotwords": { + "hey mycroft": { + "lang": "en-us", + "listen": true, + "model": "https://github.com/MycroftAI/precise-data/raw/models-dev/hey-mycroft.tar.gz", + "module": "ovos-ww-plugin-precise", + "phonemes": "HH EY . M AY K R AO F T", + "sound": "snd/start_listening.wav", + "threshold": 1e-90, + "version": "0.3" + }, + "wake up": { + "lang": "en-us", + "module": "ovos-ww-plugin-pocketsphinx", + "phonemes": "W EY K . AH P", + "threshold": 1e-20, + "wakeup": true + } + }, + "ignore_logs": [ + "enclosure.mouth.viseme", + "enclosure.mouth.display" + ], + "lang": "en-us", + "listener": { + "VAD": { + "before_seconds": 0.5, + "initial_energy_threshold": 1000.0, + "max_current_ratio_threshold": 2, + "min_seconds": 1, + "module": "", + "ovos-vad-plugin-silero": { + "threshold": 0.2 + }, + "ovos-vad-plugin-webrtcvad": { + "vad_mode": 3 + }, + "silence_method": "vad_and_ratio", + "silence_seconds": 0.5, + "speech_seconds": 0.1 + }, + "duck_while_listening": 0.3, + "energy_ratio": 1.5, + "instant_listen": false, + "mic_meter_ipc": true, + "multiplier": 1.0, + "mute_during_output": true, + "phoneme_duration": 120, + "record_wake_words": false, + "recording_timeout": 10.0, + "recording_timeout_with_silence": 3.0, + "sample_rate": 16000, + "save_utterances": false, + "wake_word_upload": { + "disable": false, + "url": "https://training.mycroft.ai/precise/upload" + } + }, + "location": { + "city": { + "code": "Lawrence", + "name": "Lawrence", + "state": { + "code": "KS", + "country": { + "code": "US", + "name": "United States" + }, + "name": "Kansas" + } + }, + "coordinate": { + "latitude": 38.971669, + "longitude": -95.23525 + }, + "timezone": { + "code": "America/Chicago", + "dstOffset": 3600000, + "name": "Central Standard Time", + "offset": -21600000 + } + }, + "network_tests": { + "dns_primary": "8.8.8.8", + "dns_secondary": "8.8.4.4", + "ncsi_endpoint": "http://www.msftncsi.com/ncsi.txt", + "ncsi_expected_text": "Microsoft NCSI", + "web_url": "https://www.google.com" + }, + "opt_in": false, + "padatious": { + "intent_cache": "~/.local/share/mycroft/intent_cache", + "padaos_only": false, + "single_thread": false, + "train_delay": 4 + }, + "play_mp3_cmdline": "mpg123 %1", + "play_ogg_cmdline": "ogg123 -q %1", + "play_wav_cmdline": "paplay %1 --stream-name=mycroft-voice", + "precise": { + "dist_url": "https://github.com/MycroftAI/precise-data/raw/dist/{arch}/latest", + "model_url": "https://raw.githubusercontent.com/MycroftAI/precise-data/models/{wake_word}.tar.gz", + "use_precise": true + }, + "ready_settings": [ + "skills" + ], + "server": { + "disabled": true, + "metrics": false, + "sync_skill_settings": true, + "update": false, + "url": "https://api.mycroft.ai", + "version": "v1" + }, + "session": { + "ttl": 180 + }, + "skills": { + "blacklisted_skills": [], + "converse": { + "converse_activation": "accept_all", + "converse_blacklist": [], + "converse_mode": "accept_all", + "converse_priorities": {}, + "converse_whitelist": [], + "cross_activation": true, + "cross_deactivation": true, + "max_activations": -1, + "skill_activations": {}, + "skill_timeouts": {}, + "timeout": 300 + }, + "directory": "skills", + "fallbacks": { + "fallback_blacklist": [], + "fallback_mode": "accept_all", + "fallback_priorities": {}, + "fallback_whitelist": [] + }, + "priority_skills": [ + "mycroft-pairing", + "mycroft-volume" + ], + "upload_skill_manifest": true, + "wait_for_internet": false + }, + "sounds": { + "acknowledge": "snd/acknowledge.mp3", + "end_listening": "snd/end_listening.wav", + "start_listening": "snd/start_listening.wav" + }, + "stt": { + "fallback_module": "ovos-stt-plugin-vosk", + "module": "ovos-stt-plugin-server", + "ovos-stt-plugin-server": { + "url": "https://stt.openvoiceos.com/stt" + } + }, + "system": { + "disable_remote_config": false, + "disable_user_config": false, + "protected_keys": { + "remote": [ + "enclosure", + "server", + "system", + "websocket", + "gui_websocket", + "network_tests", + "listener:wake_word_upload:disable", + "skills:upload_skill_manifest", + "skills:auto_update", + "skills:priority_skills", + "skills:blacklisted_skills", + "opt_in" + ], + "user": [] + } + }, + "system_unit": "metric", + "time_format": "half", + "tts": { + "fallback_module": "ovos-tts-plugin-mimic", + "module": "ovos-tts-plugin-mimic2", + "pulse_duck": false + }, + "websocket": { + "host": "0.0.0.0", + "port": 8181, + "route": "/core", + "shared_connection": true, + "ssl": false + } +} \ No newline at end of file diff --git a/test/unittests/configuration/mycroft.yml b/test/unittests/configuration/mycroft.yml new file mode 100644 index 0000000..6e5a412 --- /dev/null +++ b/test/unittests/configuration/mycroft.yml @@ -0,0 +1,193 @@ +Audio: + backends: + OCP: + active: true + type: ovos_common_play + simple: + active: true + type: ovos_audio_simple + vlc: + active: true + type: ovos_vlc + default-backend: OCP +cache_path: /tmp/mycroft/cache +confirm_listening: true +date_format: MDY +debug: false +enclosure: + force_mycroft_ntp: true + ntp_sync_on_boot: false + platform: PHAL +gui: + extension: generic + generic: + homescreen_supported: false +gui_websocket: + base_port: 18181 + host: 0.0.0.0 + route: /gui + ssl: false +hotwords: + hey mycroft: { + "lang": "en-us", + "listen": true, + "model": "https://github.com/MycroftAI/precise-data/raw/models-dev/hey-mycroft.tar.gz", + "module": "ovos-ww-plugin-precise", + "phonemes": "HH EY . M AY K R AO F T", + "sound": "snd/start_listening.wav", + "threshold": 1.0e-90, + "version": '0.3' + } + + wake up: + # Handles the "wake up" hotword when Mycroft is sleeping + lang: en-us + module: ovos-ww-plugin-pocketsphinx + phonemes: W EY K . AH P + threshold: 1.0e-20 + wakeup: true +ignore_logs: + - enclosure.mouth.viseme + - enclosure.mouth.display +lang: en-us +listener: + VAD: + before_seconds: 0.5 + initial_energy_threshold: 1000.0 + max_current_ratio_threshold: 2 + min_seconds: 1 + module: '' + ovos-vad-plugin-silero: + threshold: 0.2 + ovos-vad-plugin-webrtcvad: + vad_mode: 3 + silence_method: vad_and_ratio + silence_seconds: 0.5 + speech_seconds: 0.1 + duck_while_listening: 0.3 + energy_ratio: 1.5 + instant_listen: false + mic_meter_ipc: true + multiplier: 1.0 + mute_during_output: true + phoneme_duration: 120 + record_wake_words: false + recording_timeout: 10.0 + recording_timeout_with_silence: 3.0 + sample_rate: 16000 + save_utterances: false + wake_word_upload: + disable: false + url: https://training.mycroft.ai/precise/upload +location: + city: + code: Lawrence + name: Lawrence + state: + code: KS + country: + code: US + name: United States + name: Kansas + coordinate: + latitude: 38.971669 + longitude: -95.23525 + timezone: + code: America/Chicago + dstOffset: 3600000 + name: Central Standard Time + offset: -21600000 +network_tests: + dns_primary: 8.8.8.8 + dns_secondary: 8.8.4.4 + ncsi_endpoint: http://www.msftncsi.com/ncsi.txt + ncsi_expected_text: Microsoft NCSI + web_url: https://www.google.com +opt_in: false +padatious: + intent_cache: ~/.local/share/mycroft/intent_cache + padaos_only: false + single_thread: false + train_delay: 4 +play_mp3_cmdline: mpg123 %1 +play_ogg_cmdline: ogg123 -q %1 +play_wav_cmdline: paplay %1 --stream-name=mycroft-voice +precise: + dist_url: https://github.com/MycroftAI/precise-data/raw/dist/{arch}/latest + model_url: https://raw.githubusercontent.com/MycroftAI/precise-data/models/{wake_word}.tar.gz + use_precise: true +ready_settings: + - skills +server: + disabled: true + metrics: false + sync_skill_settings: true + update: false + url: https://api.mycroft.ai + version: v1 +session: + ttl: 180 +skills: + blacklisted_skills: [ ] + converse: + converse_activation: accept_all + converse_blacklist: [ ] + converse_mode: accept_all + converse_priorities: { } + converse_whitelist: [ ] + cross_activation: true + cross_deactivation: true + max_activations: -1 + skill_activations: { } + skill_timeouts: { } + timeout: 300 + directory: skills + fallbacks: + fallback_blacklist: [ ] + fallback_mode: accept_all + fallback_priorities: { } + fallback_whitelist: [ ] + priority_skills: + - mycroft-pairing + - mycroft-volume + upload_skill_manifest: true + wait_for_internet: false +sounds: + acknowledge: snd/acknowledge.mp3 + end_listening: snd/end_listening.wav + start_listening: snd/start_listening.wav +stt: + fallback_module: ovos-stt-plugin-vosk + module: ovos-stt-plugin-server + ovos-stt-plugin-server: + url: https://stt.openvoiceos.com/stt +system: + disable_remote_config: false + disable_user_config: false + protected_keys: + remote: + - enclosure + - server + - system + - websocket + - gui_websocket + - network_tests + - listener:wake_word_upload:disable + - skills:upload_skill_manifest + - skills:auto_update + - skills:priority_skills + - skills:blacklisted_skills + - opt_in + user: [ ] +system_unit: metric +time_format: half +tts: + fallback_module: ovos-tts-plugin-mimic + module: ovos-tts-plugin-mimic2 + pulse_duck: false +websocket: + host: 0.0.0.0 + port: 8181 + route: /core + shared_connection: true + ssl: false diff --git a/test/unittests/configuration/test_configuration.py b/test/unittests/configuration/test_configuration.py new file mode 100644 index 0000000..115d3b2 --- /dev/null +++ b/test/unittests/configuration/test_configuration.py @@ -0,0 +1,90 @@ +import json +from os.path import dirname, isfile +from typing import OrderedDict +from unittest import TestCase +from unittest.mock import MagicMock, patch + +from ovos_config import LocalConf, RemoteConf + + +# TODO - move to ovos-config +class TestConfiguration(TestCase): + + @patch('ovos_backend_client.config.RemoteConfigManager') + @patch('ovos_backend_client.pairing.is_paired') + def test_remote(self, is_paired, config_manager): + remote_conf = {'TestConfig': True, 'uuid': 1234, + 'location': {'city': {'name': 'Stockholm'}}} + is_paired.return_value = True + + mock_api = MagicMock() + mock_api.config = remote_conf + config_manager.return_value = mock_api + + rc = RemoteConf() + rc.reload() + mock_api.download.assert_called_once() + is_paired.assert_called_once() + + self.assertTrue(rc['TestConfig']) + self.assertEqual(rc['location']['city']['name'], 'Stockholm') + + @patch('json.dump') + @patch('ovos_config.models.exists') + @patch('ovos_config.models.isfile') + @patch('ovos_config.models.load_commented_json') + def test_local(self, mock_json_loader, mock_isfile, mock_exists, + mock_json_dump): + local_conf = {'answer': 42, 'falling_objects': ['flower pot', 'whale']} + mock_exists.return_value = True + mock_isfile.return_value = True + mock_json_loader.return_value = local_conf + lc = LocalConf('test') + self.assertEqual(lc, local_conf) + + # Test merge method + merge_conf = {'falling_objects': None, 'has_towel': True} + lc.merge(merge_conf) + self.assertEqual(lc['falling_objects'], None) + self.assertEqual(lc['has_towel'], True) + + # test store + lc.store('test_conf.json') + self.assertEqual(mock_json_dump.call_args[0][0], lc) + # exists but is not file + mock_isfile.return_value = False + lc = LocalConf('test') + self.assertEqual(lc, {}) + + # does not exist + mock_exists.return_value = False + lc = LocalConf('test') + self.assertEqual(lc, {}) + + def test_file_formats(self): + yml_cnf = LocalConf(f"{dirname(__file__)}/mycroft.yml") + json_config = LocalConf(f"{dirname(__file__)}/mycroft.json") + self.assertEqual(json_config, yml_cnf) + + # test export json config as yaml + json_config.store("/tmp/not_mycroft.yml") + self.assertTrue(isfile("/tmp/not_mycroft.yml")) + test_conf = LocalConf("/tmp/not_mycroft.yml") + self.assertEqual(test_conf, yml_cnf) + self.assertEqual(test_conf, json_config) + + # test export yaml config as json + yml_cnf.store("/tmp/not_mycroft.json") + self.assertTrue(isfile("/tmp/not_mycroft.json")) + test_conf = LocalConf("/tmp/not_mycroft.json") + self.assertEqual(test_conf, yml_cnf) + self.assertEqual(test_conf, json_config) + + def test_yaml_config_load(self): + yml_cnf = LocalConf(f"{dirname(__file__)}/mycroft.yml") + for d in (yml_cnf, yml_cnf["hotwords"], + yml_cnf["hotwords"]["hey mycroft"], + yml_cnf["hotwords"]["wake up"]): + self.assertIsInstance(d, dict) + self.assertNotIsInstance(d, OrderedDict) + self.assertEqual(json.loads(json.dumps(d)), d)