From 1939ef13c0a8d9d1232184914aa08c1b6d4333c9 Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Mon, 2 Oct 2023 02:54:35 +0100 Subject: [PATCH 1/4] unitests/converse --- .github/workflows/unit_tests.yml | 1 + test/end2end/session/minicroft.py | 5 +- test/end2end/session/test_converse.py | 302 ++++++++++++++++++++++++++ 3 files changed, 307 insertions(+), 1 deletion(-) create mode 100644 test/end2end/session/test_converse.py diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index 55dce5ac7240..07d85ea0990e 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -58,6 +58,7 @@ jobs: pip install ./test/end2end/session/skill-ovos-hello-world pip install ./test/end2end/session/skill-ovos-fallback-unknown pip install ./test/end2end/session/skill-ovos-fallback-unknownv1 + pip install ./test/end2end/session/skill-abort-test - name: Run unittests run: | pytest --cov=ovos_core --cov-report xml test/unittests diff --git a/test/end2end/session/minicroft.py b/test/end2end/session/minicroft.py index 310a0d9b2e3f..d178b332294a 100644 --- a/test/end2end/session/minicroft.py +++ b/test/end2end/session/minicroft.py @@ -58,7 +58,10 @@ def stop(self): def get_minicroft(skill_id): - croft1 = MiniCroft([skill_id]) + if isinstance(skill_id, str): + skill_id = [skill_id] + assert isinstance(skill_id, list) + croft1 = MiniCroft(skill_id) croft1.start() while croft1.status.state != ProcessState.READY: sleep(0.2) diff --git a/test/end2end/session/test_converse.py b/test/end2end/session/test_converse.py new file mode 100644 index 000000000000..39f95dc542de --- /dev/null +++ b/test/end2end/session/test_converse.py @@ -0,0 +1,302 @@ +import time +from time import sleep +from unittest import TestCase, skip + +from ovos_bus_client.message import Message +from ovos_bus_client.session import SessionManager, Session +from .minicroft import get_minicroft + + +class TestSessions(TestCase): + + def setUp(self): + self.skill_id = "ovos-tskill-abort.openvoiceos" + self.other_skill_id = "skill-ovos-hello-world.openvoiceos" + self.core = get_minicroft([self.skill_id, self.other_skill_id]) + + def test_no_session(self): + SessionManager.sessions = {} + SessionManager.default_session = SessionManager.sessions["default"] = Session("default") + SessionManager.default_session.lang = "en-us" + + messages = [] + + def new_msg(msg): + nonlocal messages + m = Message.deserialize(msg) + if m.msg_type in ["ovos.skills.settings_changed"]: + return # skip these, only happen in 1st run + messages.append(m) + print(len(messages), msg) + + def wait_for_n_messages(n): + nonlocal messages + t = time.time() + while len(messages) < n: + sleep(0.1) + if time.time() - t > 10: + raise RuntimeError("did not get the number of expected messages under 10 seconds") + + self.core.bus.on("message", new_msg) + + utt = Message("recognizer_loop:utterance", + {"utterances": ["no"]}) # converse returns False + self.core.bus.emit(utt) + + # confirm all expected messages are sent + expected_messages = [ + "recognizer_loop:utterance", # no session + "skill.converse.ping", # default session injected + "skill.converse.pong", + "skill.converse.pong", + # skill selected + "intent.service.skills.activated", + f"{self.skill_id}.activate", + f"{self.skill_id}:converse_off.intent", + # skill executing + "mycroft.skill.handler.start", + "enclosure.active_skill", + "speak", + "mycroft.skill.handler.complete", + # session updated + "ovos.session.update_default" + ] + wait_for_n_messages(len(expected_messages)) + + self.assertEqual(len(expected_messages), len(messages)) + + mtypes = [m.msg_type for m in messages] + for m in expected_messages: + self.assertTrue(m in mtypes) + + # verify that "session" is injected + # (missing in utterance message) and kept in all messages + for m in messages[1:]: + self.assertEqual(m.context["session"]["session_id"], "default") + + # verify that "lang" is injected by converse.ping + # (missing in utterance message) and kept in all messages + self.assertEqual(messages[1].msg_type, "skill.converse.ping") + for m in messages[1:]: + self.assertEqual(m.context["lang"], "en-us") + + # verify "pong" answer from both skills + self.assertEqual(messages[2].msg_type, "skill.converse.pong") + self.assertEqual(messages[3].msg_type, "skill.converse.pong") + self.assertEqual(messages[2].data["skill_id"],messages[2].context["skill_id"]) + self.assertEqual(messages[3].data["skill_id"], messages[3].context["skill_id"]) + # assert it reports converse method has been implemented by skill + if messages[2].data["skill_id"] == self.skill_id: # we dont know order of pong responses + self.assertTrue(messages[2].data["can_handle"]) + self.assertFalse(messages[3].data["can_handle"]) + if messages[3].data["skill_id"] == self.skill_id: # we dont know order of pong responses + self.assertTrue(messages[3].data["can_handle"]) + self.assertFalse(messages[2].data["can_handle"]) + + # verify skill is activated by intent service (intent pipeline matched) + self.assertEqual(messages[4].msg_type, "intent.service.skills.activated") + self.assertEqual(messages[4].data["skill_id"], self.skill_id) + self.assertEqual(messages[5].msg_type, f"{self.skill_id}.activate") + + # verify intent triggers + self.assertEqual(messages[6].msg_type, f"{self.skill_id}:converse_off.intent") + # verify skill_id is now present in every message.context + for m in messages[6:]: + self.assertEqual(m.context["skill_id"], self.skill_id) + + # verify intent execution + self.assertEqual(messages[7].msg_type, "mycroft.skill.handler.start") + self.assertEqual(messages[7].data["name"], "TestAbortSkill.handle_converse_off") + self.assertEqual(messages[8].msg_type, "enclosure.active_skill") + self.assertEqual(messages[8].data["skill_id"], self.skill_id) + self.assertEqual(messages[9].msg_type, "speak") + self.assertEqual(messages[9].data["lang"], "en-us") + self.assertFalse(messages[9].data["expect_response"]) + self.assertEqual(messages[9].data["meta"]["skill"], self.skill_id) + self.assertEqual(messages[10].msg_type, "mycroft.skill.handler.complete") + self.assertEqual(messages[10].data["name"], "TestAbortSkill.handle_converse_off") + + # verify default session is now updated + self.assertEqual(messages[11].msg_type, "ovos.session.update_default") + self.assertEqual(messages[11].data["session_data"]["session_id"], "default") + # test deserialization of payload + sess = Session.deserialize(messages[11].data["session_data"]) + self.assertEqual(sess.session_id, "default") + + # test that active skills list has been updated + self.assertEqual(sess.active_skills[0][0], self.skill_id) + self.assertEqual(messages[11].data["session_data"]["active_skills"][0][0], self.skill_id) + + messages = [] + + # test other skill triggers, skill says it does not want to converse + utt = Message("recognizer_loop:utterance", + {"utterances": ["hello world"]}) + self.core.bus.emit(utt) + + # confirm all expected messages are sent + expected_messages = [ + "recognizer_loop:utterance", # no session + "skill.converse.ping", # default session injected + "skill.converse.pong", + "skill.converse.pong", + "skill.converse.request", + "skill.converse.response", # does not want to converse + # skill selected + "intent.service.skills.activated", + f"{self.other_skill_id}.activate", + f"{self.other_skill_id}:HelloWorldIntent", + # skill executing + "mycroft.skill.handler.start", + "enclosure.active_skill", + "speak", + "mycroft.skill.handler.complete", + # session updated + "ovos.session.update_default" + ] + wait_for_n_messages(len(expected_messages)) + + self.assertEqual(len(expected_messages), len(messages)) + + mtypes = [m.msg_type for m in messages] + for m in expected_messages: + self.assertTrue(m in mtypes) + + # verify that "session" is injected + # (missing in utterance message) and kept in all messages + for m in messages[1:]: + self.assertEqual(m.context["session"]["session_id"], "default") + + # verify that "lang" is injected by converse.ping + # (missing in utterance message) and kept in all messages + self.assertEqual(messages[1].msg_type, "skill.converse.ping") + for m in messages[1:]: + self.assertEqual(m.context["lang"], "en-us") + + # verify "pong" answer from both skills + self.assertEqual(messages[2].msg_type, "skill.converse.pong") + self.assertEqual(messages[3].msg_type, "skill.converse.pong") + self.assertEqual(messages[2].data["skill_id"], messages[2].context["skill_id"]) + self.assertEqual(messages[3].data["skill_id"], messages[3].context["skill_id"]) + # assert it reports converse method has been implemented by skill + if messages[2].data["skill_id"] == self.skill_id: # we dont know order of pong responses + self.assertTrue(messages[2].data["can_handle"]) + self.assertFalse(messages[3].data["can_handle"]) + if messages[3].data["skill_id"] == self.skill_id: # we dont know order of pong responses + self.assertTrue(messages[3].data["can_handle"]) + self.assertFalse(messages[2].data["can_handle"]) + + # verify answer from skill that it does not want to converse + self.assertEqual(messages[4].msg_type, "skill.converse.request") + self.assertEqual(messages[4].data["skill_id"], self.skill_id) + self.assertEqual(messages[5].msg_type, "skill.converse.response") + self.assertEqual(messages[5].data["skill_id"], self.skill_id) + self.assertFalse(messages[5].data["result"]) # does not want to converse + + # verify skill is activated by intent service (intent pipeline matched) + self.assertEqual(messages[6].msg_type, "intent.service.skills.activated") + self.assertEqual(messages[6].data["skill_id"], self.other_skill_id) + self.assertEqual(messages[7].msg_type, f"{self.other_skill_id}.activate") + + # verify intent triggers + self.assertEqual(messages[8].msg_type, f"{self.other_skill_id}:HelloWorldIntent") + # verify skill_id is now present in every message.context + for m in messages[8:]: + self.assertEqual(m.context["skill_id"], self.other_skill_id) + + # verify intent execution + self.assertEqual(messages[9].msg_type, "mycroft.skill.handler.start") + self.assertEqual(messages[9].data["name"], "HelloWorldSkill.handle_hello_world_intent") + self.assertEqual(messages[10].msg_type, "enclosure.active_skill") + self.assertEqual(messages[10].data["skill_id"], self.other_skill_id) + self.assertEqual(messages[11].msg_type, "speak") + self.assertEqual(messages[11].data["lang"], "en-us") + self.assertFalse(messages[11].data["expect_response"]) + self.assertEqual(messages[11].data["meta"]["skill"], self.other_skill_id) + self.assertEqual(messages[12].msg_type, "mycroft.skill.handler.complete") + self.assertEqual(messages[12].data["name"], "HelloWorldSkill.handle_hello_world_intent") + + # verify default session is now updated + self.assertEqual(messages[13].msg_type, "ovos.session.update_default") + self.assertEqual(messages[13].data["session_data"]["session_id"], "default") + # test deserialization of payload + sess = Session.deserialize(messages[13].data["session_data"]) + self.assertEqual(sess.session_id, "default") + + # test that active skills list has been updated + self.assertEqual(sess.active_skills[0][0], self.other_skill_id) + self.assertEqual(sess.active_skills[1][0], self.skill_id) + self.assertEqual(messages[13].data["session_data"]["active_skills"][0][0], self.other_skill_id) + self.assertEqual(messages[13].data["session_data"]["active_skills"][1][0], self.skill_id) + + messages = [] + + # trigger skill intent that makes it return True in converse + # verify active skills list gets swapped again + + utt = Message("recognizer_loop:utterance", + {"utterances": ["yes"]}) # converse returns True + self.core.bus.emit(utt) + + # confirm all expected messages are sent + expected_messages = [ + "recognizer_loop:utterance", # no session + "skill.converse.ping", # default session injected + "skill.converse.pong", + "skill.converse.pong", + "skill.converse.request", + "skill.converse.response", # does not want to converse + # skill selected + "intent.service.skills.activated", + f"{self.skill_id}.activate", + f"{self.skill_id}:converse_on.intent", + # skill executing + "mycroft.skill.handler.start", + "enclosure.active_skill", + "speak", + "mycroft.skill.handler.complete", + # session updated + "ovos.session.update_default" + ] + wait_for_n_messages(len(expected_messages)) + + self.assertEqual(len(expected_messages), len(messages)) + + mtypes = [m.msg_type for m in messages] + for m in expected_messages: + self.assertTrue(m in mtypes) + + # verify that "session" is injected + # (missing in utterance message) and kept in all messages + for m in messages[1:]: + self.assertEqual(m.context["session"]["session_id"], "default") + + # verify that "lang" is injected by converse.ping + # (missing in utterance message) and kept in all messages + self.assertEqual(messages[1].msg_type, "skill.converse.ping") + for m in messages[1:]: + self.assertEqual(m.context["lang"], "en-us") + + # verify "pong" answer from both skills + self.assertEqual(messages[2].msg_type, "skill.converse.pong") + self.assertEqual(messages[3].msg_type, "skill.converse.pong") + self.assertEqual(messages[2].data["skill_id"],messages[2].context["skill_id"]) + self.assertEqual(messages[3].data["skill_id"], messages[3].context["skill_id"]) + # assert it reports converse method has been implemented by skill + if messages[2].data["skill_id"] == self.skill_id: # we dont know order of pong responses + self.assertTrue(messages[2].data["can_handle"]) + self.assertFalse(messages[3].data["can_handle"]) + if messages[3].data["skill_id"] == self.skill_id: # we dont know order of pong responses + self.assertTrue(messages[3].data["can_handle"]) + self.assertFalse(messages[2].data["can_handle"]) + + # verify answer from skill that it does not want to converse + self.assertEqual(messages[4].msg_type, "skill.converse.request") + self.assertEqual(messages[4].data["skill_id"], self.skill_id) + self.assertEqual(messages[5].msg_type, "skill.converse.response") + self.assertEqual(messages[5].data["skill_id"], self.skill_id) + + # TODO - failing here, debug converse + self.assertTrue(messages[5].data["result"]) # wants to converse + + From 1a97f40c7d4bc58dc476ad791013720ba3066af3 Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Mon, 2 Oct 2023 02:57:54 +0100 Subject: [PATCH 2/4] unitests/converse --- .github/workflows/unit_tests.yml | 2 +- .../session/skill-converse_test/__init__.py | 71 +++++++++++++++++++ .../locale/en-us/converse_off.intent | 1 + .../locale/en-us/converse_on.intent | 1 + .../locale/en-us/get.dialog | 1 + .../locale/en-us/question.dialog | 1 + .../locale/en-us/test.intent | 1 + .../locale/en-us/test2.intent | 1 + .../locale/en-us/test3.intent | 1 + .../locale/en-us/test_get_response.intent | 1 + .../session/skill-converse_test/setup.py | 39 ++++++++++ 11 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 test/end2end/session/skill-converse_test/__init__.py create mode 100644 test/end2end/session/skill-converse_test/locale/en-us/converse_off.intent create mode 100644 test/end2end/session/skill-converse_test/locale/en-us/converse_on.intent create mode 100644 test/end2end/session/skill-converse_test/locale/en-us/get.dialog create mode 100644 test/end2end/session/skill-converse_test/locale/en-us/question.dialog create mode 100644 test/end2end/session/skill-converse_test/locale/en-us/test.intent create mode 100644 test/end2end/session/skill-converse_test/locale/en-us/test2.intent create mode 100644 test/end2end/session/skill-converse_test/locale/en-us/test3.intent create mode 100644 test/end2end/session/skill-converse_test/locale/en-us/test_get_response.intent create mode 100644 test/end2end/session/skill-converse_test/setup.py diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index 07d85ea0990e..93f0a606ab2c 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -58,7 +58,7 @@ jobs: pip install ./test/end2end/session/skill-ovos-hello-world pip install ./test/end2end/session/skill-ovos-fallback-unknown pip install ./test/end2end/session/skill-ovos-fallback-unknownv1 - pip install ./test/end2end/session/skill-abort-test + pip install ./test/end2end/session/skill-converse_test - name: Run unittests run: | pytest --cov=ovos_core --cov-report xml test/unittests diff --git a/test/end2end/session/skill-converse_test/__init__.py b/test/end2end/session/skill-converse_test/__init__.py new file mode 100644 index 000000000000..04ce953bbb42 --- /dev/null +++ b/test/end2end/session/skill-converse_test/__init__.py @@ -0,0 +1,71 @@ +from ovos_workshop.decorators import killable_intent +from ovos_workshop.skills.ovos import OVOSSkill +from mycroft.skills import intent_file_handler +from time import sleep + + +class TestAbortSkill(OVOSSkill): + """ + send "mycroft.skills.abort_question" and confirm only get_response is aborted + send "mycroft.skills.abort_execution" and confirm the full intent is aborted, except intent3 + send "my.own.abort.msg" and confirm intent3 is aborted + say "stop" and confirm all intents are aborted + """ + def initialize(self): + self.stop_called = False + self._converse = False + self.add_event(f"{self.skill_id}.converse_enable", self.handle_converse_on) + self.add_event(f"{self.skill_id}.converse_disable", self.handle_converse_off) + + @intent_file_handler("converse_on.intent") + def handle_converse_on(self, message): + self._converse = True + self.speak("on") + + @intent_file_handler("converse_off.intent") + def handle_converse_off(self, message): + self._converse = False + self.speak("off") + + def handle_intent_aborted(self): + self.speak("I am dead") + + @intent_file_handler("test_get_response.intent") + def handle_test_get_response(self, message): + ans = self.get_response("get") + self.speak(ans) + + @killable_intent(callback=handle_intent_aborted) + @intent_file_handler("test.intent") + def handle_test_abort_intent(self, message): + self.stop_called = False + self.my_special_var = "changed" + while True: + sleep(1) + self.speak("still here") + + @intent_file_handler("test2.intent") + @killable_intent(callback=handle_intent_aborted) + def handle_test_get_response_intent(self, message): + self.stop_called = False + self.my_special_var = "CHANGED" + ans = self.get_response("question", num_retries=99999) + self.log.debug("get_response returned: " + str(ans)) + if ans is None: + self.speak("question aborted") + + @killable_intent(msg="my.own.abort.msg", callback=handle_intent_aborted) + @intent_file_handler("test3.intent") + def handle_test_msg_intent(self, message): + self.stop_called = False + if self.my_special_var != "default": + self.speak("someone forgot to cleanup") + while True: + sleep(1) + self.speak("you can't abort me") + + def stop(self): + self.stop_called = True + + def converse(self, message): + return self._converse diff --git a/test/end2end/session/skill-converse_test/locale/en-us/converse_off.intent b/test/end2end/session/skill-converse_test/locale/en-us/converse_off.intent new file mode 100644 index 000000000000..54299a48fb3a --- /dev/null +++ b/test/end2end/session/skill-converse_test/locale/en-us/converse_off.intent @@ -0,0 +1 @@ +no \ No newline at end of file diff --git a/test/end2end/session/skill-converse_test/locale/en-us/converse_on.intent b/test/end2end/session/skill-converse_test/locale/en-us/converse_on.intent new file mode 100644 index 000000000000..396a0ba2698c --- /dev/null +++ b/test/end2end/session/skill-converse_test/locale/en-us/converse_on.intent @@ -0,0 +1 @@ +yes \ No newline at end of file diff --git a/test/end2end/session/skill-converse_test/locale/en-us/get.dialog b/test/end2end/session/skill-converse_test/locale/en-us/get.dialog new file mode 100644 index 000000000000..1dd99dc4e0a3 --- /dev/null +++ b/test/end2end/session/skill-converse_test/locale/en-us/get.dialog @@ -0,0 +1 @@ +give me an answer \ No newline at end of file diff --git a/test/end2end/session/skill-converse_test/locale/en-us/question.dialog b/test/end2end/session/skill-converse_test/locale/en-us/question.dialog new file mode 100644 index 000000000000..f0fb83cc4f33 --- /dev/null +++ b/test/end2end/session/skill-converse_test/locale/en-us/question.dialog @@ -0,0 +1 @@ +this is a question \ No newline at end of file diff --git a/test/end2end/session/skill-converse_test/locale/en-us/test.intent b/test/end2end/session/skill-converse_test/locale/en-us/test.intent new file mode 100644 index 000000000000..30d74d258442 --- /dev/null +++ b/test/end2end/session/skill-converse_test/locale/en-us/test.intent @@ -0,0 +1 @@ +test \ No newline at end of file diff --git a/test/end2end/session/skill-converse_test/locale/en-us/test2.intent b/test/end2end/session/skill-converse_test/locale/en-us/test2.intent new file mode 100644 index 000000000000..5161aff42996 --- /dev/null +++ b/test/end2end/session/skill-converse_test/locale/en-us/test2.intent @@ -0,0 +1 @@ +test again \ No newline at end of file diff --git a/test/end2end/session/skill-converse_test/locale/en-us/test3.intent b/test/end2end/session/skill-converse_test/locale/en-us/test3.intent new file mode 100644 index 000000000000..1fec3fd265bf --- /dev/null +++ b/test/end2end/session/skill-converse_test/locale/en-us/test3.intent @@ -0,0 +1 @@ +one more test \ No newline at end of file diff --git a/test/end2end/session/skill-converse_test/locale/en-us/test_get_response.intent b/test/end2end/session/skill-converse_test/locale/en-us/test_get_response.intent new file mode 100644 index 000000000000..88cde3244be1 --- /dev/null +++ b/test/end2end/session/skill-converse_test/locale/en-us/test_get_response.intent @@ -0,0 +1 @@ +test get response \ No newline at end of file diff --git a/test/end2end/session/skill-converse_test/setup.py b/test/end2end/session/skill-converse_test/setup.py new file mode 100644 index 000000000000..211ae750b309 --- /dev/null +++ b/test/end2end/session/skill-converse_test/setup.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +from setuptools import setup +from os import getenv, path, walk + + +def find_resource_files(): + resource_base_dirs = ("locale", "ui", "vocab", "dialog", "regex") + base_dir = path.dirname(__file__) + package_data = ["skill.json"] + for res in resource_base_dirs: + if path.isdir(path.join(base_dir, res)): + for (directory, _, files) in walk(path.join(base_dir, res)): + if files: + package_data.append( + path.join(directory.replace(base_dir, "").lstrip('/'), + '*')) + return package_data + + +# skill_id=package_name:SkillClass +PLUGIN_ENTRY_POINT = 'ovos-tskill-abort.openvoiceos=ovos_tskill_abort:TestAbortSkill' + +setup( + # this is the package name that goes on pip + name='ovos-tskill-abort', + version='0.0.1', + description='this is a OVOS test skill for the killable_intents decorator', + url='https://github.com/OpenVoiceOS/skill-abort-test', + author='JarbasAi', + author_email='jarbasai@mailfence.com', + license='Apache-2.0', + package_dir={"ovos_tskill_abort": ""}, + package_data={'ovos_tskill_abort': find_resource_files()}, + packages=['ovos_tskill_abort'], + include_package_data=True, + install_requires=["ovos-workshop"], + keywords='ovos skill plugin', + entry_points={'ovos.plugin.skill': PLUGIN_ENTRY_POINT} +) From 3bf456d9cc1b8289fb3a0326bf75ae6442f6ad76 Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Mon, 2 Oct 2023 03:19:03 +0100 Subject: [PATCH 3/4] unitests/converse --- test/end2end/session/test_converse.py | 648 ++++++++++++++++---------- 1 file changed, 390 insertions(+), 258 deletions(-) diff --git a/test/end2end/session/test_converse.py b/test/end2end/session/test_converse.py index 39f95dc542de..c114f98534cc 100644 --- a/test/end2end/session/test_converse.py +++ b/test/end2end/session/test_converse.py @@ -39,264 +39,396 @@ def wait_for_n_messages(n): self.core.bus.on("message", new_msg) - utt = Message("recognizer_loop:utterance", - {"utterances": ["no"]}) # converse returns False - self.core.bus.emit(utt) - - # confirm all expected messages are sent - expected_messages = [ - "recognizer_loop:utterance", # no session - "skill.converse.ping", # default session injected - "skill.converse.pong", - "skill.converse.pong", - # skill selected - "intent.service.skills.activated", - f"{self.skill_id}.activate", - f"{self.skill_id}:converse_off.intent", - # skill executing - "mycroft.skill.handler.start", - "enclosure.active_skill", - "speak", - "mycroft.skill.handler.complete", - # session updated - "ovos.session.update_default" - ] - wait_for_n_messages(len(expected_messages)) - - self.assertEqual(len(expected_messages), len(messages)) - - mtypes = [m.msg_type for m in messages] - for m in expected_messages: - self.assertTrue(m in mtypes) - - # verify that "session" is injected - # (missing in utterance message) and kept in all messages - for m in messages[1:]: - self.assertEqual(m.context["session"]["session_id"], "default") - - # verify that "lang" is injected by converse.ping - # (missing in utterance message) and kept in all messages - self.assertEqual(messages[1].msg_type, "skill.converse.ping") - for m in messages[1:]: - self.assertEqual(m.context["lang"], "en-us") - - # verify "pong" answer from both skills - self.assertEqual(messages[2].msg_type, "skill.converse.pong") - self.assertEqual(messages[3].msg_type, "skill.converse.pong") - self.assertEqual(messages[2].data["skill_id"],messages[2].context["skill_id"]) - self.assertEqual(messages[3].data["skill_id"], messages[3].context["skill_id"]) - # assert it reports converse method has been implemented by skill - if messages[2].data["skill_id"] == self.skill_id: # we dont know order of pong responses - self.assertTrue(messages[2].data["can_handle"]) - self.assertFalse(messages[3].data["can_handle"]) - if messages[3].data["skill_id"] == self.skill_id: # we dont know order of pong responses - self.assertTrue(messages[3].data["can_handle"]) - self.assertFalse(messages[2].data["can_handle"]) - - # verify skill is activated by intent service (intent pipeline matched) - self.assertEqual(messages[4].msg_type, "intent.service.skills.activated") - self.assertEqual(messages[4].data["skill_id"], self.skill_id) - self.assertEqual(messages[5].msg_type, f"{self.skill_id}.activate") - - # verify intent triggers - self.assertEqual(messages[6].msg_type, f"{self.skill_id}:converse_off.intent") - # verify skill_id is now present in every message.context - for m in messages[6:]: - self.assertEqual(m.context["skill_id"], self.skill_id) - - # verify intent execution - self.assertEqual(messages[7].msg_type, "mycroft.skill.handler.start") - self.assertEqual(messages[7].data["name"], "TestAbortSkill.handle_converse_off") - self.assertEqual(messages[8].msg_type, "enclosure.active_skill") - self.assertEqual(messages[8].data["skill_id"], self.skill_id) - self.assertEqual(messages[9].msg_type, "speak") - self.assertEqual(messages[9].data["lang"], "en-us") - self.assertFalse(messages[9].data["expect_response"]) - self.assertEqual(messages[9].data["meta"]["skill"], self.skill_id) - self.assertEqual(messages[10].msg_type, "mycroft.skill.handler.complete") - self.assertEqual(messages[10].data["name"], "TestAbortSkill.handle_converse_off") - - # verify default session is now updated - self.assertEqual(messages[11].msg_type, "ovos.session.update_default") - self.assertEqual(messages[11].data["session_data"]["session_id"], "default") - # test deserialization of payload - sess = Session.deserialize(messages[11].data["session_data"]) - self.assertEqual(sess.session_id, "default") - - # test that active skills list has been updated - self.assertEqual(sess.active_skills[0][0], self.skill_id) - self.assertEqual(messages[11].data["session_data"]["active_skills"][0][0], self.skill_id) + # triggers intent from test skill to make it active + # verify active skills list (test) + def skill_converse_no(): - messages = [] - - # test other skill triggers, skill says it does not want to converse - utt = Message("recognizer_loop:utterance", - {"utterances": ["hello world"]}) - self.core.bus.emit(utt) - - # confirm all expected messages are sent - expected_messages = [ - "recognizer_loop:utterance", # no session - "skill.converse.ping", # default session injected - "skill.converse.pong", - "skill.converse.pong", - "skill.converse.request", - "skill.converse.response", # does not want to converse - # skill selected - "intent.service.skills.activated", - f"{self.other_skill_id}.activate", - f"{self.other_skill_id}:HelloWorldIntent", - # skill executing - "mycroft.skill.handler.start", - "enclosure.active_skill", - "speak", - "mycroft.skill.handler.complete", - # session updated - "ovos.session.update_default" - ] - wait_for_n_messages(len(expected_messages)) - - self.assertEqual(len(expected_messages), len(messages)) - - mtypes = [m.msg_type for m in messages] - for m in expected_messages: - self.assertTrue(m in mtypes) - - # verify that "session" is injected - # (missing in utterance message) and kept in all messages - for m in messages[1:]: - self.assertEqual(m.context["session"]["session_id"], "default") - - # verify that "lang" is injected by converse.ping - # (missing in utterance message) and kept in all messages - self.assertEqual(messages[1].msg_type, "skill.converse.ping") - for m in messages[1:]: - self.assertEqual(m.context["lang"], "en-us") - - # verify "pong" answer from both skills - self.assertEqual(messages[2].msg_type, "skill.converse.pong") - self.assertEqual(messages[3].msg_type, "skill.converse.pong") - self.assertEqual(messages[2].data["skill_id"], messages[2].context["skill_id"]) - self.assertEqual(messages[3].data["skill_id"], messages[3].context["skill_id"]) - # assert it reports converse method has been implemented by skill - if messages[2].data["skill_id"] == self.skill_id: # we dont know order of pong responses - self.assertTrue(messages[2].data["can_handle"]) - self.assertFalse(messages[3].data["can_handle"]) - if messages[3].data["skill_id"] == self.skill_id: # we dont know order of pong responses - self.assertTrue(messages[3].data["can_handle"]) - self.assertFalse(messages[2].data["can_handle"]) - - # verify answer from skill that it does not want to converse - self.assertEqual(messages[4].msg_type, "skill.converse.request") - self.assertEqual(messages[4].data["skill_id"], self.skill_id) - self.assertEqual(messages[5].msg_type, "skill.converse.response") - self.assertEqual(messages[5].data["skill_id"], self.skill_id) - self.assertFalse(messages[5].data["result"]) # does not want to converse - - # verify skill is activated by intent service (intent pipeline matched) - self.assertEqual(messages[6].msg_type, "intent.service.skills.activated") - self.assertEqual(messages[6].data["skill_id"], self.other_skill_id) - self.assertEqual(messages[7].msg_type, f"{self.other_skill_id}.activate") - - # verify intent triggers - self.assertEqual(messages[8].msg_type, f"{self.other_skill_id}:HelloWorldIntent") - # verify skill_id is now present in every message.context - for m in messages[8:]: - self.assertEqual(m.context["skill_id"], self.other_skill_id) - - # verify intent execution - self.assertEqual(messages[9].msg_type, "mycroft.skill.handler.start") - self.assertEqual(messages[9].data["name"], "HelloWorldSkill.handle_hello_world_intent") - self.assertEqual(messages[10].msg_type, "enclosure.active_skill") - self.assertEqual(messages[10].data["skill_id"], self.other_skill_id) - self.assertEqual(messages[11].msg_type, "speak") - self.assertEqual(messages[11].data["lang"], "en-us") - self.assertFalse(messages[11].data["expect_response"]) - self.assertEqual(messages[11].data["meta"]["skill"], self.other_skill_id) - self.assertEqual(messages[12].msg_type, "mycroft.skill.handler.complete") - self.assertEqual(messages[12].data["name"], "HelloWorldSkill.handle_hello_world_intent") - - # verify default session is now updated - self.assertEqual(messages[13].msg_type, "ovos.session.update_default") - self.assertEqual(messages[13].data["session_data"]["session_id"], "default") - # test deserialization of payload - sess = Session.deserialize(messages[13].data["session_data"]) - self.assertEqual(sess.session_id, "default") - - # test that active skills list has been updated - self.assertEqual(sess.active_skills[0][0], self.other_skill_id) - self.assertEqual(sess.active_skills[1][0], self.skill_id) - self.assertEqual(messages[13].data["session_data"]["active_skills"][0][0], self.other_skill_id) - self.assertEqual(messages[13].data["session_data"]["active_skills"][1][0], self.skill_id) - - messages = [] - - # trigger skill intent that makes it return True in converse - # verify active skills list gets swapped again - - utt = Message("recognizer_loop:utterance", - {"utterances": ["yes"]}) # converse returns True - self.core.bus.emit(utt) - - # confirm all expected messages are sent - expected_messages = [ - "recognizer_loop:utterance", # no session - "skill.converse.ping", # default session injected - "skill.converse.pong", - "skill.converse.pong", - "skill.converse.request", - "skill.converse.response", # does not want to converse - # skill selected - "intent.service.skills.activated", - f"{self.skill_id}.activate", - f"{self.skill_id}:converse_on.intent", - # skill executing - "mycroft.skill.handler.start", - "enclosure.active_skill", - "speak", - "mycroft.skill.handler.complete", - # session updated - "ovos.session.update_default" - ] - wait_for_n_messages(len(expected_messages)) - - self.assertEqual(len(expected_messages), len(messages)) - - mtypes = [m.msg_type for m in messages] - for m in expected_messages: - self.assertTrue(m in mtypes) - - # verify that "session" is injected - # (missing in utterance message) and kept in all messages - for m in messages[1:]: - self.assertEqual(m.context["session"]["session_id"], "default") - - # verify that "lang" is injected by converse.ping - # (missing in utterance message) and kept in all messages - self.assertEqual(messages[1].msg_type, "skill.converse.ping") - for m in messages[1:]: - self.assertEqual(m.context["lang"], "en-us") - - # verify "pong" answer from both skills - self.assertEqual(messages[2].msg_type, "skill.converse.pong") - self.assertEqual(messages[3].msg_type, "skill.converse.pong") - self.assertEqual(messages[2].data["skill_id"],messages[2].context["skill_id"]) - self.assertEqual(messages[3].data["skill_id"], messages[3].context["skill_id"]) - # assert it reports converse method has been implemented by skill - if messages[2].data["skill_id"] == self.skill_id: # we dont know order of pong responses - self.assertTrue(messages[2].data["can_handle"]) - self.assertFalse(messages[3].data["can_handle"]) - if messages[3].data["skill_id"] == self.skill_id: # we dont know order of pong responses - self.assertTrue(messages[3].data["can_handle"]) - self.assertFalse(messages[2].data["can_handle"]) - - # verify answer from skill that it does not want to converse - self.assertEqual(messages[4].msg_type, "skill.converse.request") - self.assertEqual(messages[4].data["skill_id"], self.skill_id) - self.assertEqual(messages[5].msg_type, "skill.converse.response") - self.assertEqual(messages[5].data["skill_id"], self.skill_id) - - # TODO - failing here, debug converse - self.assertTrue(messages[5].data["result"]) # wants to converse + nonlocal messages + utt = Message("recognizer_loop:utterance", + {"utterances": ["no"]}) # converse returns False + self.core.bus.emit(utt) + + # confirm all expected messages are sent + expected_messages = [ + "recognizer_loop:utterance", # no session + "skill.converse.ping", # default session injected + "skill.converse.pong", + "skill.converse.pong", + # skill selected + "intent.service.skills.activated", + f"{self.skill_id}.activate", + f"{self.skill_id}:converse_off.intent", + # skill executing + "mycroft.skill.handler.start", + "enclosure.active_skill", + "speak", + "mycroft.skill.handler.complete", + # session updated + "ovos.session.update_default" + ] + wait_for_n_messages(len(expected_messages)) + + self.assertEqual(len(expected_messages), len(messages)) + + mtypes = [m.msg_type for m in messages] + for m in expected_messages: + self.assertTrue(m in mtypes) + + # verify that "session" is injected + # (missing in utterance message) and kept in all messages + for m in messages[1:]: + self.assertEqual(m.context["session"]["session_id"], "default") + + # verify that "lang" is injected by converse.ping + # (missing in utterance message) and kept in all messages + self.assertEqual(messages[1].msg_type, "skill.converse.ping") + for m in messages[1:]: + self.assertEqual(m.context["lang"], "en-us") + + # verify "pong" answer from both skills + self.assertEqual(messages[2].msg_type, "skill.converse.pong") + self.assertEqual(messages[3].msg_type, "skill.converse.pong") + self.assertEqual(messages[2].data["skill_id"],messages[2].context["skill_id"]) + self.assertEqual(messages[3].data["skill_id"], messages[3].context["skill_id"]) + # assert it reports converse method has been implemented by skill + if messages[2].data["skill_id"] == self.skill_id: # we dont know order of pong responses + self.assertTrue(messages[2].data["can_handle"]) + self.assertFalse(messages[3].data["can_handle"]) + if messages[3].data["skill_id"] == self.skill_id: # we dont know order of pong responses + self.assertTrue(messages[3].data["can_handle"]) + self.assertFalse(messages[2].data["can_handle"]) + + # verify skill is activated by intent service (intent pipeline matched) + self.assertEqual(messages[4].msg_type, "intent.service.skills.activated") + self.assertEqual(messages[4].data["skill_id"], self.skill_id) + self.assertEqual(messages[5].msg_type, f"{self.skill_id}.activate") + + # verify intent triggers + self.assertEqual(messages[6].msg_type, f"{self.skill_id}:converse_off.intent") + # verify skill_id is now present in every message.context + for m in messages[6:]: + self.assertEqual(m.context["skill_id"], self.skill_id) + + # verify intent execution + self.assertEqual(messages[7].msg_type, "mycroft.skill.handler.start") + self.assertEqual(messages[7].data["name"], "TestAbortSkill.handle_converse_off") + self.assertEqual(messages[8].msg_type, "enclosure.active_skill") + self.assertEqual(messages[8].data["skill_id"], self.skill_id) + self.assertEqual(messages[9].msg_type, "speak") + self.assertEqual(messages[9].data["lang"], "en-us") + self.assertFalse(messages[9].data["expect_response"]) + self.assertEqual(messages[9].data["meta"]["skill"], self.skill_id) + self.assertEqual(messages[10].msg_type, "mycroft.skill.handler.complete") + self.assertEqual(messages[10].data["name"], "TestAbortSkill.handle_converse_off") + + # verify default session is now updated + self.assertEqual(messages[11].msg_type, "ovos.session.update_default") + self.assertEqual(messages[11].data["session_data"]["session_id"], "default") + # test deserialization of payload + sess = Session.deserialize(messages[11].data["session_data"]) + self.assertEqual(sess.session_id, "default") + + # test that active skills list has been updated + self.assertEqual(sess.active_skills[0][0], self.skill_id) + self.assertEqual(messages[11].data["session_data"]["active_skills"][0][0], self.skill_id) + + messages = [] + + skill_converse_no() + + # test hello world skill triggers, test skill says it does not want to converse + # verify active skills list (hello, test) + def hello_world(): + nonlocal messages + utt = Message("recognizer_loop:utterance", + {"utterances": ["hello world"]}) + self.core.bus.emit(utt) + + # confirm all expected messages are sent + expected_messages = [ + "recognizer_loop:utterance", # no session + "skill.converse.ping", # default session injected + "skill.converse.pong", + "skill.converse.pong", + "skill.converse.request", + "skill.converse.response", # does not want to converse + # skill selected + "intent.service.skills.activated", + f"{self.other_skill_id}.activate", + f"{self.other_skill_id}:HelloWorldIntent", + # skill executing + "mycroft.skill.handler.start", + "enclosure.active_skill", + "speak", + "mycroft.skill.handler.complete", + # session updated + "ovos.session.update_default" + ] + wait_for_n_messages(len(expected_messages)) + + self.assertEqual(len(expected_messages), len(messages)) + + mtypes = [m.msg_type for m in messages] + for m in expected_messages: + self.assertTrue(m in mtypes) + + # verify that "session" is injected + # (missing in utterance message) and kept in all messages + for m in messages[1:]: + self.assertEqual(m.context["session"]["session_id"], "default") + + # verify that "lang" is injected by converse.ping + # (missing in utterance message) and kept in all messages + self.assertEqual(messages[1].msg_type, "skill.converse.ping") + for m in messages[1:]: + self.assertEqual(m.context["lang"], "en-us") + + # verify "pong" answer from both skills + self.assertEqual(messages[2].msg_type, "skill.converse.pong") + self.assertEqual(messages[3].msg_type, "skill.converse.pong") + self.assertEqual(messages[2].data["skill_id"], messages[2].context["skill_id"]) + self.assertEqual(messages[3].data["skill_id"], messages[3].context["skill_id"]) + # assert it reports converse method has been implemented by skill + if messages[2].data["skill_id"] == self.skill_id: # we dont know order of pong responses + self.assertTrue(messages[2].data["can_handle"]) + self.assertFalse(messages[3].data["can_handle"]) + if messages[3].data["skill_id"] == self.skill_id: # we dont know order of pong responses + self.assertTrue(messages[3].data["can_handle"]) + self.assertFalse(messages[2].data["can_handle"]) + + # verify answer from skill that it does not want to converse + self.assertEqual(messages[4].msg_type, "skill.converse.request") + self.assertEqual(messages[4].data["skill_id"], self.skill_id) + self.assertEqual(messages[5].msg_type, "skill.converse.response") + self.assertEqual(messages[5].data["skill_id"], self.skill_id) + self.assertFalse(messages[5].data["result"]) # does not want to converse + + # verify skill is activated by intent service (intent pipeline matched) + self.assertEqual(messages[6].msg_type, "intent.service.skills.activated") + self.assertEqual(messages[6].data["skill_id"], self.other_skill_id) + self.assertEqual(messages[7].msg_type, f"{self.other_skill_id}.activate") + + # verify intent triggers + self.assertEqual(messages[8].msg_type, f"{self.other_skill_id}:HelloWorldIntent") + # verify skill_id is now present in every message.context + for m in messages[8:]: + self.assertEqual(m.context["skill_id"], self.other_skill_id) + + # verify intent execution + self.assertEqual(messages[9].msg_type, "mycroft.skill.handler.start") + self.assertEqual(messages[9].data["name"], "HelloWorldSkill.handle_hello_world_intent") + self.assertEqual(messages[10].msg_type, "enclosure.active_skill") + self.assertEqual(messages[10].data["skill_id"], self.other_skill_id) + self.assertEqual(messages[11].msg_type, "speak") + self.assertEqual(messages[11].data["lang"], "en-us") + self.assertFalse(messages[11].data["expect_response"]) + self.assertEqual(messages[11].data["meta"]["skill"], self.other_skill_id) + self.assertEqual(messages[12].msg_type, "mycroft.skill.handler.complete") + self.assertEqual(messages[12].data["name"], "HelloWorldSkill.handle_hello_world_intent") + + # verify default session is now updated + self.assertEqual(messages[13].msg_type, "ovos.session.update_default") + self.assertEqual(messages[13].data["session_data"]["session_id"], "default") + # test deserialization of payload + sess = Session.deserialize(messages[13].data["session_data"]) + self.assertEqual(sess.session_id, "default") + + # test that active skills list has been updated + self.assertEqual(sess.active_skills[0][0], self.other_skill_id) + self.assertEqual(sess.active_skills[1][0], self.skill_id) + self.assertEqual(messages[13].data["session_data"]["active_skills"][0][0], self.other_skill_id) + self.assertEqual(messages[13].data["session_data"]["active_skills"][1][0], self.skill_id) + + messages = [] + + hello_world() + + # trigger skill intent that makes it return True in next converse + # verify active skills list gets swapped (test, hello) + def skill_converse_yes(): + nonlocal messages + utt = Message("recognizer_loop:utterance", + {"utterances": ["yes"]}) # converse returns True + self.core.bus.emit(utt) + + # confirm all expected messages are sent + expected_messages = [ + "recognizer_loop:utterance", # no session + "skill.converse.ping", # default session injected + "skill.converse.pong", + "skill.converse.pong", + "skill.converse.request", + "skill.converse.response", # does not want to converse + # skill selected + "intent.service.skills.activated", + f"{self.skill_id}.activate", + f"{self.skill_id}:converse_on.intent", + # skill executing + "mycroft.skill.handler.start", + "enclosure.active_skill", + "speak", + "mycroft.skill.handler.complete", + # session updated + "ovos.session.update_default" + ] + wait_for_n_messages(len(expected_messages)) + + self.assertEqual(len(expected_messages), len(messages)) + + mtypes = [m.msg_type for m in messages] + for m in expected_messages: + self.assertTrue(m in mtypes) + + # verify that "session" is injected + # (missing in utterance message) and kept in all messages + for m in messages[1:]: + self.assertEqual(m.context["session"]["session_id"], "default") + + # verify that "lang" is injected by converse.ping + # (missing in utterance message) and kept in all messages + self.assertEqual(messages[1].msg_type, "skill.converse.ping") + for m in messages[1:]: + self.assertEqual(m.context["lang"], "en-us") + + # verify "pong" answer from both skills + self.assertEqual(messages[2].msg_type, "skill.converse.pong") + self.assertEqual(messages[3].msg_type, "skill.converse.pong") + self.assertEqual(messages[2].data["skill_id"],messages[2].context["skill_id"]) + self.assertEqual(messages[3].data["skill_id"], messages[3].context["skill_id"]) + # assert it reports converse method has been implemented by skill + if messages[2].data["skill_id"] == self.skill_id: # we dont know order of pong responses + self.assertTrue(messages[2].data["can_handle"]) + self.assertFalse(messages[3].data["can_handle"]) + if messages[3].data["skill_id"] == self.skill_id: # we dont know order of pong responses + self.assertTrue(messages[3].data["can_handle"]) + self.assertFalse(messages[2].data["can_handle"]) + + # verify answer from skill that it does not want to converse + self.assertEqual(messages[4].msg_type, "skill.converse.request") + self.assertEqual(messages[4].data["skill_id"], self.skill_id) + self.assertEqual(messages[5].msg_type, "skill.converse.response") + self.assertEqual(messages[5].data["skill_id"], self.skill_id) + self.assertFalse(messages[5].data["result"]) # do not want to converse + + # verify skill is activated by intent service (intent pipeline matched) + self.assertEqual(messages[6].msg_type, "intent.service.skills.activated") + self.assertEqual(messages[6].data["skill_id"], self.skill_id) + self.assertEqual(messages[7].msg_type, f"{self.skill_id}.activate") + + # verify intent triggers + self.assertEqual(messages[8].msg_type, f"{self.skill_id}:converse_on.intent") + # verify skill_id is now present in every message.context + for m in messages[8:]: + self.assertEqual(m.context["skill_id"], self.skill_id) + + # verify intent execution + self.assertEqual(messages[9].msg_type, "mycroft.skill.handler.start") + self.assertEqual(messages[9].data["name"], "TestAbortSkill.handle_converse_on") + self.assertEqual(messages[10].msg_type, "enclosure.active_skill") + self.assertEqual(messages[10].data["skill_id"], self.skill_id) + self.assertEqual(messages[11].msg_type, "speak") + self.assertEqual(messages[11].data["lang"], "en-us") + self.assertFalse(messages[11].data["expect_response"]) + self.assertEqual(messages[11].data["meta"]["skill"], self.skill_id) + self.assertEqual(messages[12].msg_type, "mycroft.skill.handler.complete") + self.assertEqual(messages[12].data["name"], "TestAbortSkill.handle_converse_on") + + # verify default session is now updated + self.assertEqual(messages[13].msg_type, "ovos.session.update_default") + self.assertEqual(messages[13].data["session_data"]["session_id"], "default") + # test deserialization of payload + sess = Session.deserialize(messages[13].data["session_data"]) + self.assertEqual(sess.session_id, "default") + + # test that active skills list has been updated + self.assertEqual(sess.active_skills[0][0], self.skill_id) + self.assertEqual(sess.active_skills[1][0], self.other_skill_id) + self.assertEqual(messages[13].data["session_data"]["active_skills"][0][0], self.skill_id) + self.assertEqual(messages[13].data["session_data"]["active_skills"][1][0], self.other_skill_id) + + messages = [] + + skill_converse_yes() + + # test converse capture, hello world utterance wont reach hello world skill + def converse_capture(): + nonlocal messages + utt = Message("recognizer_loop:utterance", + {"utterances": ["hello world"]}) + self.core.bus.emit(utt) + + # confirm all expected messages are sent + expected_messages = [ + "recognizer_loop:utterance", # no session + "skill.converse.ping", # default session injected + "skill.converse.pong", + "skill.converse.pong", + "skill.converse.request", + "skill.converse.response", # CONVERSED + # skill selected + "intent.service.skills.activated", + f"{self.skill_id}.activate", + # session updated + "ovos.session.update_default" + ] + wait_for_n_messages(len(expected_messages)) + + self.assertEqual(len(expected_messages), len(messages)) + + mtypes = [m.msg_type for m in messages] + for m in expected_messages: + print(m) + self.assertTrue(m in mtypes) + + # verify that "session" is injected + # (missing in utterance message) and kept in all messages + for m in messages[1:]: + self.assertEqual(m.context["session"]["session_id"], "default") + + # verify that "lang" is injected by converse.ping + # (missing in utterance message) and kept in all messages + self.assertEqual(messages[1].msg_type, "skill.converse.ping") + for m in messages[1:]: + self.assertEqual(m.context["lang"], "en-us") + + # verify "pong" answer from both skills + self.assertEqual(messages[2].msg_type, "skill.converse.pong") + self.assertEqual(messages[3].msg_type, "skill.converse.pong") + self.assertEqual(messages[2].data["skill_id"], messages[2].context["skill_id"]) + self.assertEqual(messages[3].data["skill_id"], messages[3].context["skill_id"]) + # assert it reports converse method has been implemented by skill + if messages[2].data["skill_id"] == self.skill_id: # we dont know order of pong responses + self.assertTrue(messages[2].data["can_handle"]) + self.assertFalse(messages[3].data["can_handle"]) + if messages[3].data["skill_id"] == self.skill_id: # we dont know order of pong responses + self.assertTrue(messages[3].data["can_handle"]) + self.assertFalse(messages[2].data["can_handle"]) + + # verify answer from skill that it does not want to converse + self.assertEqual(messages[4].msg_type, "skill.converse.request") + self.assertEqual(messages[4].data["skill_id"], self.skill_id) + self.assertEqual(messages[5].msg_type, "skill.converse.response") + self.assertEqual(messages[5].data["skill_id"], self.skill_id) + self.assertTrue(messages[5].data["result"]) # CONVERSED + + # verify skill is activated by intent service (intent pipeline matched) + self.assertEqual(messages[6].msg_type, "intent.service.skills.activated") + self.assertEqual(messages[6].data["skill_id"], self.skill_id) + self.assertEqual(messages[7].msg_type, f"{self.skill_id}.activate") + + # verify default session is now updated + self.assertEqual(messages[8].msg_type, "ovos.session.update_default") + self.assertEqual(messages[8].data["session_data"]["session_id"], "default") + # test deserialization of payload + sess = Session.deserialize(messages[8].data["session_data"]) + self.assertEqual(sess.session_id, "default") + + # test that active skills list has been updated + self.assertEqual(sess.active_skills[0][0], self.skill_id) + self.assertEqual(sess.active_skills[1][0], self.other_skill_id) + self.assertEqual(messages[8].data["session_data"]["active_skills"][0][0], self.skill_id) + self.assertEqual(messages[8].data["session_data"]["active_skills"][1][0], self.other_skill_id) + + converse_capture() From 830a79088aefcc5e4c7e7f2efb9649e58344ef6c Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Mon, 2 Oct 2023 03:26:29 +0100 Subject: [PATCH 4/4] update codecov --- .github/workflows/unit_tests.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index 93f0a606ab2c..618795d129c0 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -77,9 +77,17 @@ jobs: pip install .[lgpl] - name: Run unittests with padatious run: | - pytest --cov=ovos_core --cov-report xml test/unittests/skills + pytest --cov-append --cov=ovos_core --cov-report xml test/unittests/skills - name: Upload coverage if: "${{ matrix.python-version == '3.9' }}" env: CODECOV_TOKEN: ${{secrets.CODECOV_TOKEN}} - uses: codecov/codecov-action@v2 \ No newline at end of file + uses: codecov/codecov-action@v3 + with: + token: ${{ secrets.CODECOV_TOKEN }} + directory: ./coverage/reports/ + fail_ci_if_error: true + files: ./coverage.xml,!./cache + flags: unittests + name: codecov-umbrella + verbose: true \ No newline at end of file