From c2bb2e0db9297c448a08e6b5259b829c4ad7099b Mon Sep 17 00:00:00 2001 From: JarbasAI <33701864+JarbasAl@users.noreply.github.com> Date: Mon, 2 Oct 2023 04:55:57 +0100 Subject: [PATCH] unittests/skill_self_activation (#360) --- ovos_core/intent_services/converse_service.py | 6 ++ .../session/skill-converse_test/__init__.py | 10 +- test/end2end/session/test_converse.py | 93 +++++++++++++++++++ test/end2end/session/test_fallback_v1.py | 25 +++-- 4 files changed, 122 insertions(+), 12 deletions(-) diff --git a/ovos_core/intent_services/converse_service.py b/ovos_core/intent_services/converse_service.py index c62b142df8b..81313ab7efd 100644 --- a/ovos_core/intent_services/converse_service.py +++ b/ovos_core/intent_services/converse_service.py @@ -330,6 +330,9 @@ def handle_activate_skill_request(self, message): skill_id = message.data['skill_id'] source_skill = message.context.get("skill_id") self.activate_skill(skill_id, source_skill, message) + sess = SessionManager.get(message) + if sess.session_id == "default": + SessionManager.sync(message) def handle_deactivate_skill_request(self, message): # TODO imperfect solution - only a skill can deactivate itself @@ -339,6 +342,9 @@ def handle_deactivate_skill_request(self, message): skill_id = message.data['skill_id'] source_skill = message.context.get("skill_id") or skill_id self.deactivate_skill(skill_id, source_skill, message) + sess = SessionManager.get(message) + if sess.session_id == "default": + SessionManager.sync(message) def reset_converse(self, message): """Let skills know there was a problem with speech recognition""" diff --git a/test/end2end/session/skill-converse_test/__init__.py b/test/end2end/session/skill-converse_test/__init__.py index 04ce953bbb4..93cd6291988 100644 --- a/test/end2end/session/skill-converse_test/__init__.py +++ b/test/end2end/session/skill-converse_test/__init__.py @@ -14,8 +14,14 @@ class TestAbortSkill(OVOSSkill): 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) + self.bus.on("test_activate", self.do_activate) + self.bus.on("test_deactivate", self.do_deactivate) + + def do_activate(self, message): + self.activate() + + def do_deactivate(self, message): + self.deactivate() @intent_file_handler("converse_on.intent") def handle_converse_on(self, message): diff --git a/test/end2end/session/test_converse.py b/test/end2end/session/test_converse.py index c114f98534c..984a7273c69 100644 --- a/test/end2end/session/test_converse.py +++ b/test/end2end/session/test_converse.py @@ -431,4 +431,97 @@ def converse_capture(): 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) + messages = [] + converse_capture() + + def external_deactivate(): + nonlocal messages + + utt = Message("test_deactivate") + self.core.bus.emit(utt) + + self.assertEqual(SessionManager.default_session.active_skills[0][0], self.other_skill_id) + # confirm all expected messages are sent + expected_messages = [ + "test_deactivate", + "intent.service.skills.deactivate", + "intent.service.skills.deactivated", + "ovos-tskill-abort.openvoiceos.deactivate", + "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 skill is no longer in active skills + self.assertEqual(SessionManager.default_session.active_skills[0][0], self.other_skill_id) + self.assertEqual(len(SessionManager.default_session.active_skills), 1) + + # verify default session is now updated + self.assertEqual(messages[-1].msg_type, "ovos.session.update_default") + self.assertEqual(messages[-1].data["session_data"]["session_id"], "default") + # test deserialization of payload + sess = Session.deserialize(messages[-1].data["session_data"]) + self.assertEqual(sess.session_id, "default") + # test that active skills list has been updated + self.assertEqual(len(sess.active_skills), 1) + self.assertEqual(sess.active_skills[0][0], self.other_skill_id) + self.assertEqual(len(messages[-1].data["session_data"]["active_skills"]), 1) + self.assertEqual(messages[-1].data["session_data"]["active_skills"][0][0], self.other_skill_id) + + messages = [] + + external_deactivate() + + def external_activate(): + nonlocal messages + + self.assertEqual(SessionManager.default_session.active_skills[0][0], self.other_skill_id) + utt = Message("test_activate") + self.core.bus.emit(utt) + self.assertEqual(SessionManager.default_session.active_skills[0][0], self.skill_id) + # confirm all expected messages are sent + expected_messages = [ + "test_activate", + "intent.service.skills.activate", + "intent.service.skills.activated", + f"{self.skill_id}.activate", + "ovos.session.update_default", + "active_skill_request", # backwards compat namespace classic core + "intent.service.skills.activated", + f"{self.skill_id}.activate", + "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 skill is again in active skills + self.assertEqual(SessionManager.default_session.active_skills[0][0], self.skill_id) + self.assertEqual(len(SessionManager.default_session.active_skills), 2) + + # verify default session is now updated + self.assertEqual(messages[-1].msg_type, "ovos.session.update_default") + self.assertEqual(messages[-1].data["session_data"]["session_id"], "default") + # test deserialization of payload + sess = Session.deserialize(messages[-1].data["session_data"]) + self.assertEqual(sess.session_id, "default") + # test that active skills list has been updated + self.assertEqual(len(sess.active_skills), 2) + self.assertEqual(sess.active_skills[0][0], self.skill_id) + self.assertEqual(len(messages[-1].data["session_data"]["active_skills"]), 2) + self.assertEqual(messages[-1].data["session_data"]["active_skills"][0][0], self.skill_id) + + messages = [] + + external_activate() + diff --git a/test/end2end/session/test_fallback_v1.py b/test/end2end/session/test_fallback_v1.py index 18a43e37bb0..853ab1e4bfc 100644 --- a/test/end2end/session/test_fallback_v1.py +++ b/test/end2end/session/test_fallback_v1.py @@ -64,13 +64,16 @@ def wait_for_n_messages(n): "mycroft.skill.handler.start", "enclosure.active_skill", "speak", + # self activation from skill, instead of from core "intent.service.skills.activate", "intent.service.skills.activated", f"{self.skill_id}.activate", + "ovos.session.update_default", # because it comes from skill # backwards compat activation for older cores "active_skill_request", "intent.service.skills.activated", f"{self.skill_id}.activate", + "ovos.session.update_default", # because it comes from skill # report handling "mycroft.skill.handler.complete", "mycroft.skills.fallback.response", @@ -140,22 +143,24 @@ def wait_for_n_messages(n): self.assertEqual(messages[16].msg_type, "intent.service.skills.activated") self.assertEqual(messages[16].data["skill_id"], self.skill_id) self.assertEqual(messages[17].msg_type, f"{self.skill_id}.activate") + self.assertEqual(messages[18].msg_type, 'ovos.session.update_default') # skill making itself active again - backwards compat namespace - self.assertEqual(messages[18].msg_type, "active_skill_request") - self.assertEqual(messages[18].data["skill_id"], self.skill_id) - self.assertEqual(messages[19].msg_type, "intent.service.skills.activated") + self.assertEqual(messages[19].msg_type, "active_skill_request") self.assertEqual(messages[19].data["skill_id"], self.skill_id) - self.assertEqual(messages[20].msg_type, f"{self.skill_id}.activate") + self.assertEqual(messages[20].msg_type, "intent.service.skills.activated") + self.assertEqual(messages[20].data["skill_id"], self.skill_id) + self.assertEqual(messages[21].msg_type, f"{self.skill_id}.activate") + self.assertEqual(messages[22].msg_type, 'ovos.session.update_default') # fallback execution response - self.assertEqual(messages[21].msg_type, "mycroft.skill.handler.complete") - self.assertEqual(messages[21].data["handler"], "fallback") - self.assertEqual(messages[22].msg_type, "mycroft.skills.fallback.response") - self.assertTrue(messages[22].data["handled"]) + self.assertEqual(messages[23].msg_type, "mycroft.skill.handler.complete") + self.assertEqual(messages[23].data["handler"], "fallback") + self.assertEqual(messages[24].msg_type, "mycroft.skills.fallback.response") + self.assertTrue(messages[24].data["handled"]) # verify default session is now updated - self.assertEqual(messages[23].msg_type, "ovos.session.update_default") - self.assertEqual(messages[23].data["session_data"]["session_id"], "default") + self.assertEqual(messages[25].msg_type, "ovos.session.update_default") + self.assertEqual(messages[25].data["session_data"]["session_id"], "default") # test second message with no session resumes default active skills messages = []