From b548c2da0b4f577bb162c778e420f5929e8dff8b Mon Sep 17 00:00:00 2001 From: JarbasAI <33701864+JarbasAl@users.noreply.github.com> Date: Tue, 3 Oct 2023 00:51:12 +0100 Subject: [PATCH] fix/get_response some more (#362) --- requirements/requirements.txt | 2 +- test/end2end/session/test_get_response.py | 120 +++++++++++++++--- .../skills/test_mycroft_skill_get_response.py | 4 +- 3 files changed, 105 insertions(+), 21 deletions(-) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index b37687542e8..572ff93d65d 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -12,7 +12,7 @@ ovos-plugin-manager<0.1.0, >=0.0.24a9 ovos-config~=0.0,>=0.0.11a13 ovos-lingua-franca>=0.4.7 ovos-backend-client>=0.1.0a12 -ovos-workshop<0.1.0, >=0.0.13a8 +ovos-workshop<0.1.0, >=0.0.13a9 # provides plugins and classic machine learning framework ovos-classifiers<0.1.0, >=0.0.0a37 diff --git a/test/end2end/session/test_get_response.py b/test/end2end/session/test_get_response.py index 8ca92ffcdcb..cbbb4153648 100644 --- a/test/end2end/session/test_get_response.py +++ b/test/end2end/session/test_get_response.py @@ -58,10 +58,10 @@ def wait_for_n_messages(n): # skill executing "mycroft.skill.handler.start", - "enclosure.active_skill", - "speak", # 'mycroft.mic.listen' if no dialog passed to get_response "skill.converse.get_response.enable", # start of get_response "ovos.session.update_default", # sync get_response status + "enclosure.active_skill", + "speak", # 'mycroft.mic.listen' if no dialog passed to get_response # "recognizer_loop:utterance" would be here if user answered "skill.converse.get_response.disable", # end of get_response "ovos.session.update_default", # sync get_response status @@ -119,16 +119,18 @@ def wait_for_n_messages(n): # verify intent execution self.assertEqual(messages[7].msg_type, "mycroft.skill.handler.start") self.assertEqual(messages[7].data["name"], "TestAbortSkill.handle_test_get_response") - 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.assertTrue(messages[9].data["expect_response"]) # listen after dialog - self.assertEqual(messages[9].data["meta"]["skill"], self.skill_id) # enable get_response for this session - self.assertEqual(messages[10].msg_type, "skill.converse.get_response.enable") - self.assertEqual(messages[11].msg_type, "ovos.session.update_default") + self.assertEqual(messages[8].msg_type, "skill.converse.get_response.enable") + self.assertEqual(messages[9].msg_type, "ovos.session.update_default") + + # question dialog + 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.assertTrue(messages[11].data["expect_response"]) # listen after dialog + self.assertEqual(messages[11].data["meta"]["skill"], self.skill_id) # user response would be here @@ -181,13 +183,14 @@ def wait_for_n_messages(n): self.core.bus.on("message", new_msg) def answer_get_response(msg): - sleep(0.5) - utt = Message("recognizer_loop:utterance", - {"utterances": ["ok"]}, - {"session": SessionManager.default_session.serialize()}) - self.core.bus.emit(utt) + if msg.data["utterance"] == "give me an answer": + sleep(0.5) + utt = Message("recognizer_loop:utterance", + {"utterances": ["ok"]}, + {"session": SessionManager.default_session.serialize()}) + self.core.bus.emit(utt) - self.core.bus.on("skill.converse.get_response.enable", answer_get_response) + self.core.bus.on("speak", answer_get_response) # trigger get_response utt = Message("recognizer_loop:utterance", @@ -208,10 +211,10 @@ def answer_get_response(msg): # intent code before self.get_response "mycroft.skill.handler.start", - "enclosure.active_skill", - "speak", # 'mycroft.mic.listen' if no dialog passed to get_response "skill.converse.get_response.enable", # start of get_response "ovos.session.update_default", # sync get_response status + "enclosure.active_skill", + "speak", # 'mycroft.mic.listen' if no dialog passed to get_response "recognizer_loop:utterance", # answer to get_response from user, # converse pipeline start @@ -224,15 +227,17 @@ def answer_get_response(msg): f"{self.skill_id}.activate", "ovos.session.update_default", # sync skill activated by converse - # intent code post self.get_response "skill.converse.get_response.disable", # end of get_response "ovos.session.update_default", # sync get_response status + + # intent code post self.get_response "enclosure.active_skill", # from speak inside intent "speak", # speak "ok" inside intent "mycroft.skill.handler.complete", # original intent finished executing # session updated at end of intent pipeline "ovos.session.update_default" + ] wait_for_n_messages(len(expected_messages)) @@ -247,3 +252,80 @@ def answer_get_response(msg): for m in messages[1:]: print(m.msg_type, m.context["session"]["session_id"]) self.assertEqual(m.context["session"]["session_id"], "default") + + # converse intent pipeline + self.assertEqual(messages[1].msg_type, "skill.converse.ping") + 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}:test_get_response.intent") + + # verify intent execution + self.assertEqual(messages[7].msg_type, "mycroft.skill.handler.start") + self.assertEqual(messages[7].data["name"], "TestAbortSkill.handle_test_get_response") + + # enable get_response for this session + self.assertEqual(messages[8].msg_type, "skill.converse.get_response.enable") + self.assertEqual(messages[9].msg_type, "ovos.session.update_default") + + 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["utterance"], "give me an answer", ) + self.assertEqual(messages[11].data["lang"], "en-us") + self.assertTrue(messages[11].data["expect_response"]) # listen after dialog + self.assertEqual(messages[11].data["meta"]["skill"], self.skill_id) + + # check utterance goes through converse cycle + self.assertEqual(messages[12].msg_type, "recognizer_loop:utterance") + self.assertEqual(messages[13].msg_type, "skill.converse.ping") + self.assertEqual(messages[14].msg_type, "skill.converse.pong") + self.assertEqual(messages[15].msg_type, "skill.converse.pong") + + # captured utterance sent to get_response handler that is waiting + self.assertEqual(messages[16].msg_type, "skill.converse.get_response") + self.assertEqual(messages[16].data["skill_id"], self.skill_id) + self.assertEqual(messages[16].data["utterances"], ["ok"]) + + # converse pipeline activates the skill last_used timestamp + self.assertEqual(messages[17].msg_type, "intent.service.skills.activated") + self.assertEqual(messages[18].msg_type, f"{self.skill_id}.activate") + self.assertEqual(messages[19].msg_type, "ovos.session.update_default") + + # disable get_response for this session + self.assertEqual(messages[20].msg_type, "skill.converse.get_response.disable") + self.assertEqual(messages[21].msg_type, "ovos.session.update_default") + + # post self.get_response intent code + self.assertEqual(messages[22].msg_type, "enclosure.active_skill") + self.assertEqual(messages[22].data["skill_id"], self.skill_id) + self.assertEqual(messages[23].msg_type, "speak") + self.assertEqual(messages[23].data["lang"], "en-us") + self.assertFalse(messages[23].data["expect_response"]) + self.assertEqual(messages[23].data["utterance"], "ok") + self.assertEqual(messages[23].data["meta"]["skill"], self.skill_id) + + self.assertEqual(messages[24].msg_type, "mycroft.skill.handler.complete") + self.assertEqual(messages[24].data["name"], "TestAbortSkill.handle_test_get_response") + + # verify default session is now updated + self.assertEqual(messages[25].msg_type, "ovos.session.update_default") + self.assertEqual(messages[25].data["session_data"]["session_id"], "default") + # test deserialization of payload + sess = Session.deserialize(messages[25].data["session_data"]) + self.assertEqual(sess.session_id, "default") diff --git a/test/unittests/skills/test_mycroft_skill_get_response.py b/test/unittests/skills/test_mycroft_skill_get_response.py index 0970c92dd2f..b8b9f9ac24b 100644 --- a/test/unittests/skills/test_mycroft_skill_get_response.py +++ b/test/unittests/skills/test_mycroft_skill_get_response.py @@ -1,6 +1,7 @@ """Tests for the mycroft skill's get_response variations.""" import time +import unittest from os.path import dirname, join from threading import Thread from unittest import TestCase, mock, skip @@ -54,8 +55,8 @@ def create_skill(mock_conf, lang='en-us'): return skill +@skip("TODO - refactor for new event based get_response") class TestMycroftSkillWaitResponse(TestCase): - @skip("TODO - refactor for new event based get_response") def test_wait(self): """Ensure that _wait_response() returns the response from converse.""" skill = create_skill() @@ -122,6 +123,7 @@ def test_get_response_text(self): expect_response=True, wait=True) + @unittest.skip("TODO - modernize") def test_get_response_no_dialog(self): """Check that when no dialog/text is provided listening is triggered. """