class TestTakkRules(unittest.TestCase): __dummy_file = 'test_action_dummy_file' def setUp(self): Config.get_config('conf/main.test.conf') from rules import Rules self.rules = Rules('conf/speech.test.xml') def test_pattern_matched(self): patterns = self.rules.pattern_match('play some music artist Led Zeppelin') self.assertGreater(len(patterns), 0) self.assertEqual(patterns[0]['id'], 'play-music') self.assertEqual(patterns[0]['attributes']['artist'], 'Led Zeppelin') def test_pattern_not_matched(self): patterns = self.rules.pattern_match('this will never be matched by any of my rules') self.assertEqual(len(patterns), 0) def test_non_existing_action(self): self.assertRaises(KeyError, self.rules.run_action, 'non-existing-action') def test_get_rules_by_pattern(self): rules = self.rules.get_rules_by_patterns(['create-file']) self.assertEqual(len(rules), 1) self.assertEqual(rules[0], 'create-test-file-shell-on-create-file') action_ids = self.rules.get_actions_by_rule(rules[0]) self.assertEqual(len(action_ids), 1) self.assertEqual(action_ids[0], 'create-test-file-shell') def test_get_rules_by_multiple_patterns(self): rules = self.rules.get_rules_by_patterns(['create-file', 'remove-file']) self.assertEqual(len(rules), 1) self.assertEqual(rules[0], 'create-and-remove-test-file-shell-on-double-command') action_ids = self.rules.get_actions_by_rule(rules[0]) self.assertEqual(len(action_ids), 2) self.assertEqual(action_ids[0], 'create-test-file-shell') self.assertEqual(action_ids[1], 'remove-test-file-shell') def test_get_rules_by_non_existing_pattern(self): rules = self.rules.get_rules_by_patterns(['i-dont-exist']) self.assertEqual(len(rules), 0) def test_shell_action(self): self.rules.run_action('create-test-file-shell', {'filename': self.__dummy_file } ) self.assertTrue(os.path.isfile(self.__dummy_file)) self.rules.run_action('remove-test-file-shell', {'filename': self.__dummy_file } ) self.assertFalse(os.path.isfile(self.__dummy_file)) def test_python_action(self): self.rules.run_action('create-test-file-python', {'filename': self.__dummy_file } ) self.assertTrue(os.path.isfile(self.__dummy_file)) self.rules.run_action('remove-test-file-python', {'filename': self.__dummy_file } ) self.assertFalse(os.path.isfile(self.__dummy_file)) def tearDown(self): if os.path.isfile(self.__dummy_file): os.remove(self.__dummy_file)
def __init__(self): self.__logger.info({ 'msg_type': 'Application started', 'config': self.__config.dump(), }) audio = AudioSource() audio.record_to_flac() speech = SpeechRecognition() text = None confidence = None try: text, confidence = speech.recognize_speech_from_file() self.__logger.info({ 'msg_type': 'Speech recognized', 'text': text, 'confidence': confidence, }) except SpeechRecognitionError as e: # TODO Properly manage the raised exception with a retry mechanism, see #13 self.__logger.info({ 'msg_type': 'Speech not recognized', }) rules = Rules('rules.xml') patterns = rules.pattern_match(text.strip()) if len(patterns) == 0: self.__logger.info({ 'msg_type': 'No pattern matched', 'text': text, }) else: self.__logger.info({ 'msg_type': 'Pattern matched', 'text': text, 'patterns': json.dumps(patterns), }) pattern_ids = list(map(lambda _: _['id'], patterns)) matched_rules = rules.get_rules_by_patterns(pattern_ids) if len(matched_rules) == 0: self.__logger.info({ 'msg_type': 'No rules associated to the matched patterns', 'patterns': json.dumps(patterns), }) else: self.__logger.info({ 'msg_type': 'Rules found', 'patterns': json.dumps(patterns), 'rules': json.dumps(matched_rules), }) # TODO We only pick up the first rule for now. # Eventually we should build a map of all the # actions associated to the matched patterns # according to the provided rules and establish # a priority for executing all of them. rule = matched_rules[0] actions = rules.get_actions_by_rule(rule) for action in actions: rules.run_action(action)