瀏覽代碼

Merge pull request #92 from kalliope-project/tests_monf

Tests monf
Nicolas Marcq 8 年之前
父節點
當前提交
e2a8731523
共有 45 個文件被更改,包括 941 次插入46 次删除
  1. 13 0
      .travis.yml
  2. 2 0
      README.md
  3. 0 0
      Tests/__init__.py
  4. 0 0
      Tests/brains/brain_test.yml
  5. 0 0
      Tests/brains/included_brain_test.yml
  6. 0 0
      Tests/settings/settings_test.yml
  7. 3 3
      Tests/test_brain_loader.py
  8. 0 0
      Tests/test_configuration_checker.py
  9. 6 6
      Tests/test_dynamic_loading.py
  10. 108 5
      Tests/test_order_analyser.py
  11. 152 0
      Tests/test_rest_api.py
  12. 1 3
      Tests/test_settings_loader.py
  13. 120 0
      Tests/test_tts_module.py
  14. 1 1
      Tests/test_yaml_loader.py
  15. 14 3
      core/RestAPI/FlaskAPI.py
  16. 10 9
      core/TTS/TTSModule.py
  17. 24 0
      install/files/deb-packages_requirements.txt
  18. 1 0
      install/files/python_requirements.txt
  19. 3 0
      install/files/travis_repo_trusty_requirements.txt
  20. 0 2
      install/install.yml
  21. 0 0
      neurons/ansible_playbook/tests/__init__.py
  22. 31 0
      neurons/ansible_playbook/tests/test_ansible_playbook.py
  23. 0 0
      neurons/gmail_checker/tests/__init__.py
  24. 37 0
      neurons/gmail_checker/tests/test_gmail_checker.py
  25. 4 4
      neurons/openweathermap/openweathermap.py
  26. 0 0
      neurons/openweathermap/tests/__init__.py
  27. 36 0
      neurons/openweathermap/tests/test_openweathermap.py
  28. 4 4
      neurons/push_message/push_message.py
  29. 0 0
      neurons/push_message/tests/__init__.py
  30. 46 0
      neurons/push_message/tests/test_push_message.py
  31. 0 0
      neurons/say/tests/__init__.py
  32. 27 0
      neurons/say/tests/test_say.py
  33. 0 0
      neurons/script/tests/__init__.py
  34. 61 0
      neurons/script/tests/test_script.py
  35. 0 0
      neurons/shell/tests/__init__.py
  36. 30 0
      neurons/shell/tests/test_shell.py
  37. 0 0
      neurons/sleep/tests/__init__.py
  38. 30 0
      neurons/sleep/tests/test_sleep.py
  39. 0 0
      neurons/tasker_autoremote/tests/__init__.py
  40. 36 0
      neurons/tasker_autoremote/tests/test_tasker_autoremote.py
  41. 0 0
      neurons/twitter/tests/__init__.py
  42. 68 0
      neurons/twitter/tests/test_twitter_neuron.py
  43. 6 6
      neurons/twitter/twitter.py
  44. 0 0
      neurons/wake_on_lan/tests/__init__.py
  45. 67 0
      neurons/wake_on_lan/tests/test_wake_on_lan.py

+ 13 - 0
.travis.yml

@@ -0,0 +1,13 @@
+language: python
+python:
+  - "2.7"
+# command to install dependencies
+before_install:
+- sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu trusty main restricted universe multiverse"
+- sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu trusty-updates main restricted universe multiverse"
+- sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu trusty-backports main restricted universe multiverse"
+- sudo apt-get update
+- sudo apt-get install $(cat install/files/deb-packages_requirements.txt)
+install: "pip install -r install/files/python_requirements.txt"
+# command to run tests
+script: pytest

+ 2 - 0
README.md

@@ -1,5 +1,7 @@
 # Kalliope
 
+[![Build Status](https://travis-ci.org/kalliope-project/kalliope.svg?branch=tests_monf)](https://travis-ci.org/kalliope-project/kalliope)
+
 ![logo](images/Kalliope_logo_large.png)
 
 Kalliope is a modular always-on voice controlled personal assistant designed for home automation.

+ 0 - 0
core/Tests/__init__.py → Tests/__init__.py


+ 0 - 0
core/Tests/brains/brain_test.yml → Tests/brains/brain_test.yml


+ 0 - 0
core/Tests/brains/included_brain_test.yml → Tests/brains/included_brain_test.yml


+ 0 - 0
core/Tests/settings/settings_test.yml → Tests/settings/settings_test.yml


+ 3 - 3
core/Tests/test_brain_loader.py → Tests/test_brain_loader.py

@@ -1,17 +1,17 @@
 import unittest
 
 from core.ConfigurationManager import BrainLoader
-from core.Models import Brain
 from core.Models import Event
 from core.Models import Neuron
-from core.Models import Order
 from core.Models import Synapse
+from core.Models import Order
+from core.Models.Brain import Brain
 
 
 class TestBrainLoader(unittest.TestCase):
 
     def setUp(self):
-        self.brain_to_test = "core/Tests/brains/brain_test.yml"
+        self.brain_to_test = "Tests/brains/brain_test.yml"
         self.expected_result = [
             {'signals': [{'order': 'test_order'}],
              'neurons': [{'say': {'message': ['test message']}}],

+ 0 - 0
core/Tests/test_configuration_checker.py → Tests/test_configuration_checker.py


+ 6 - 6
core/Tests/test_dynamic_loading.py → Tests/test_dynamic_loading.py

@@ -18,7 +18,7 @@ class TestDynamicLoading(unittest.TestCase):
         # get current script directory path. We are in /an/unknown/path/kalliope/core/Tests
         cur_script_directory = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
         # get parent dir. Now we are in /an/unknown/path/kalliope
-        root_dir = os.path.normpath(cur_script_directory + os.sep + os.pardir + os.sep + os.pardir)
+        root_dir = os.path.normpath(cur_script_directory + os.sep + os.pardir)
 
         # get the neuron dir
         self.neurons_dir = os.path.normpath(root_dir + os.sep + "neurons")
@@ -32,7 +32,7 @@ class TestDynamicLoading(unittest.TestCase):
         # get trigger dir
         self.trigger_dir = os.path.normpath(root_dir + os.sep + "trigger")
 
-    def test_01_packages_present(self):
+    def test_packages_present(self):
         """
         Check that the neurons folder exist in the root of the project
         """
@@ -41,7 +41,7 @@ class TestDynamicLoading(unittest.TestCase):
         self.assertTrue(os.path.isdir(self.tts_dir))
         self.assertTrue(os.path.isdir(self.trigger_dir))
 
-    def test_02_can_import_neurons(self):
+    def test_can_import_neurons(self):
         """
         Try to import each neurons that are present in the neurons package
         :return:
@@ -52,7 +52,7 @@ class TestDynamicLoading(unittest.TestCase):
             module_name = neuron_name.capitalize()
             self.dynamic_import(package_name, module_name)
 
-    def test_03_can_import_stt(self):
+    def test_can_import_stt(self):
         """
         Try to import each stt that are present in the stt package
         :return:
@@ -63,7 +63,7 @@ class TestDynamicLoading(unittest.TestCase):
             module_name = stt_name.capitalize()
             self.dynamic_import(package_name, module_name)
 
-    def test_04_can_import_tts(self):
+    def test_can_import_tts(self):
         """
         Try to import each tts that are present in the tts package
         :return:
@@ -74,7 +74,7 @@ class TestDynamicLoading(unittest.TestCase):
             module_name = tts_name.capitalize()
             self.dynamic_import(package_name, module_name)
 
-    def test_05_can_import_trigger(self):
+    def test_can_import_trigger(self):
         """
         Try to import each trigger that are present in the trigger package
         :return:

+ 108 - 5
core/Tests/test_order_analyser.py → Tests/test_order_analyser.py

@@ -206,7 +206,7 @@ class TestOrderAnalyser(unittest.TestCase):
 
         signal1 = Order(sentence="this is the sentence")
         signal2 = Order(sentence="this is the second sentence")
-        signal3 = Order(sentence="this is the third sentence")
+        signal3 = Order(sentence="that is part of the third sentence")
 
         synapse1 = Synapse(name="Synapse1", neurons=[neuron1, neuron2], signals=[signal1])
         synapse2 = Synapse(name="Synapse2", neurons=[neuron3, neuron4], signals=[signal2])
@@ -223,9 +223,53 @@ class TestOrderAnalyser(unittest.TestCase):
         self.assertEquals(OrderAnalyser._get_matching_synapse_list(all_synapses_list=all_synapse_list,
                                                                    order_to_match=order_to_match),
                           expected_result,
-                          "Fail matching the expected synapse from the complete synapse list and the order")
+                          "Fail matching 'the expected synapse' from the complete synapse list and the order")
 
-        # TODO : to be continued
+        # Multiple Matching synapses
+        signal2 = Order(sentence="this is the sentence")
+
+        synapse2 = Synapse(name="Synapse2", neurons=[neuron3, neuron4], signals=[signal2])
+        order_to_match = "this is the sentence"
+
+        all_synapse_list = [synapse1,
+                            synapse2,
+                            synapse3]
+
+        expected_result = [synapse1,
+                           synapse2]
+        self.assertEquals(OrderAnalyser._get_matching_synapse_list(all_synapses_list=all_synapse_list,
+                                                                   order_to_match=order_to_match),
+                          expected_result,
+                          "Fail 'Multiple Matching synapses' from the complete synapse list and the order")
+
+        # matching no synapses
+        order_to_match = "this is not the correct word"
+
+        all_synapse_list = [synapse1,
+                            synapse2,
+                            synapse3]
+
+        expected_result = []
+
+        self.assertEquals(OrderAnalyser._get_matching_synapse_list(all_synapses_list=all_synapse_list,
+                                                                   order_to_match=order_to_match),
+                          expected_result,
+                          "Fail matching 'no synapses' from the complete synapse list and the order")
+
+        # matching synapse with all key worlds
+        # /!\ Some words in the order are matching all words in synapses signals !
+        order_to_match = "this is not the correct sentence"
+        all_synapse_list = [synapse1,
+                            synapse2,
+                            synapse3]
+
+        expected_result = [synapse1,
+                           synapse2]
+
+        self.assertEquals(OrderAnalyser._get_matching_synapse_list(all_synapses_list=all_synapse_list,
+                                                                   order_to_match=order_to_match),
+                          expected_result,
+                          "Fail matching 'synapse with all key worlds' from the complete synapse list and the order")
 
     def test_get_synapse_params(self):
         # Init
@@ -241,10 +285,69 @@ class TestOrderAnalyser(unittest.TestCase):
 
         self.assertEquals(OrderAnalyser._get_synapse_params(synapse=synapse1, order_to_check=order_to_check),
                           expected_result,
-                          "Fail to retrieve the params of the synapse from the order")
+                          "Fail to retrieve 'the params' of the synapse from the order")
+
+        # Multiple match
+        signal1 = Order(sentence="this is the {{ sentence }}")
+
+        synapse1 = Synapse(name="Synapse1", neurons=[neuron1, neuron2], signals=[signal1])
+
+        order_to_check = "this is the value with multiple words"
+        expected_result = {'sentence': 'value with multiple words'}
+
+        self.assertEqual(OrderAnalyser._get_synapse_params(synapse=synapse1, order_to_check=order_to_check),
+                         expected_result,
+                         "Fail to retrieve the 'multiple words params' of the synapse from the order")
+
+        # Multiple params
+        signal1 = Order(sentence="this is the {{ sentence }} with multiple {{ params }}")
+
+        synapse1 = Synapse(name="Synapse1", neurons=[neuron1, neuron2], signals=[signal1])
+
+        order_to_check = "this is the value with multiple words"
+        expected_result = {'sentence': 'value',
+                            'params':'words'}
+
+        self.assertEqual(OrderAnalyser._get_synapse_params(synapse=synapse1, order_to_check=order_to_check),
+                         expected_result,
+                         "Fail to retrieve the 'multiple params' of the synapse from the order")
+
+        # Multiple params with multiple words
+        signal1 = Order(sentence="this is the {{ sentence }} with multiple {{ params }}")
+
+        synapse1 = Synapse(name="Synapse1", neurons=[neuron1, neuron2], signals=[signal1])
+
+        order_to_check = "this is the multiple values with multiple values as words"
+        expected_result = {'sentence': 'multiple values',
+                           'params': 'values as words'}
+
+        self.assertEqual(OrderAnalyser._get_synapse_params(synapse=synapse1, order_to_check=order_to_check),
+                         expected_result,
+                         "Fail to retrieve the 'multiple params with multiple words' of the synapse from the order")
+
+        # params at the begining of the sentence
+        signal1 = Order(sentence="{{ sentence }} this is the sentence")
+
+        synapse1 = Synapse(name="Synapse1", neurons=[neuron1, neuron2], signals=[signal1])
+
+        order_to_check = "hello world this is the multiple values with multiple values as words"
+        expected_result = {'sentence': 'hello world'}
+
+        self.assertEqual(OrderAnalyser._get_synapse_params(synapse=synapse1, order_to_check=order_to_check),
+                         expected_result,
+                         "Fail to retrieve the 'params at the begining of the sentence' of the synapse from the order")
+
+        # all of the sentence is a variable
+        signal1 = Order(sentence="{{ sentence }}")
+
+        synapse1 = Synapse(name="Synapse1", neurons=[neuron1, neuron2], signals=[signal1])
 
-        # TODO : to be continued
+        order_to_check = "this is the all sentence is a variable"
+        expected_result = {'sentence': 'this is the all sentence is a variable'}
 
+        self.assertEqual(OrderAnalyser._get_synapse_params(synapse=synapse1, order_to_check=order_to_check),
+                         expected_result,
+                         "Fail to retrieve the 'all of the sentence is a variable' of the synapse from the order")
 
 if __name__ == '__main__':
     unittest.main()

+ 152 - 0
Tests/test_rest_api.py

@@ -0,0 +1,152 @@
+import json
+import unittest
+
+import requests
+import time
+from flask import Flask
+
+from core.ConfigurationManager import BrainLoader
+from core.ConfigurationManager import SettingLoader
+from core.RestAPI.FlaskAPI import FlaskAPI
+
+
+class TestRestAPI(unittest.TestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        """
+        executed once at the beginning of the test
+        """
+        # rest api config
+        sl = SettingLoader.Instance()
+        sl.settings.rest_api.password_protected = False
+        sl.settings.active = True
+        sl.settings.port = 5000
+        # prepare a test brain
+        brain_to_test = "Tests/brains/brain_test.yml"
+        brain_loader = BrainLoader.Instance(file_path=brain_to_test)
+        brain = brain_loader.brain
+
+        app = Flask(__name__)
+        cls.flask_api = FlaskAPI(app, port=5000, brain=brain)
+        cls.flask_api.start()
+        time.sleep(1)
+
+    @classmethod
+    def tearDownClass(cls):
+        """
+        executed once at the end of the test
+        """
+        url = "http://127.0.0.1:5000/shutdown/"
+        requests.post(url=url)
+
+    def setUp(self):
+        self.base_url = "http://127.0.0.1:5000"
+
+    def test_get_synapses(self):
+        url = self.base_url+"/synapses/"
+        result = requests.get(url=url)
+
+        expected_content = {
+            "synapses": [
+                {
+                    "name": "test",
+                    "neurons": [
+                        {
+                            "say": {
+                                "message": [
+                                    "test message"
+                                ]
+                            }
+                        }
+                    ],
+                    "signals": [
+                        {
+                            "order": "test_order"
+                        }
+                    ]
+                },
+                {
+                    "name": "test2",
+                    "neurons": [
+                        {
+                            "say": {
+                                "message": [
+                                    "test message"
+                                ]
+                            }
+                        }
+                    ],
+                    "signals": [
+                        {
+                            "order": "test_order_2"
+                        }
+                    ]
+                },
+                {
+                    "includes": [
+                        "included_brain_test.yml"
+                    ]
+                },
+                {
+                    "name": "test3",
+                    "neurons": [
+                        {
+                            "say": {
+                                "message": [
+                                    "test message"
+                                ]
+                            }
+                        }
+                    ],
+                    "signals": [
+                        {
+                            "order": "test_order_3"
+                        }
+                    ]
+                }
+            ]
+        }
+
+        self.assertEqual(expected_content, json.loads(result.content))
+
+    def test_get_one_synapse(self):
+        url = self.base_url+"/synapses/test"
+        result = requests.get(url=url)
+
+        expected_content = {
+            "synapses": {
+                "name": "test",
+                "neurons": [
+                    {
+                        "say": {
+                            "message": [
+                                "test message"
+                            ]
+                        }
+                    }
+                ],
+                "signals": [
+                    {
+                        "order": "test_order"
+                    }
+                ]
+            }
+        }
+
+        self.assertEqual(expected_content, json.loads(result.content))
+
+    def test_synapse_not_found(self):
+        url = self.base_url + "/synapses/test-none"
+        result = requests.get(url=url)
+
+        expected_content = {
+            "error": {
+                "synapse name not found": "test-none"
+            }
+        }
+
+        self.assertEqual(expected_content, json.loads(result.content))
+
+if __name__ == '__main__':
+    unittest.main()

+ 1 - 3
core/Tests/test_settings_loader.py → Tests/test_settings_loader.py

@@ -1,9 +1,7 @@
-import platform
 import unittest
 
 from core.ConfigurationManager import SettingLoader
 from core.Models.RestAPI import RestAPI
-from core.Models.Settings import Settings
 from core.Models.Stt import Stt
 from core.Models.Trigger import Trigger
 from core.Models.Tts import Tts
@@ -13,7 +11,7 @@ class TestSettingLoader(unittest.TestCase):
 
     def setUp(self):
 
-        self.settings_file_to_test = "core/Tests/settings/settings_test.yml"
+        self.settings_file_to_test = "Tests/settings/settings_test.yml"
 
         self.settings_dict = {
             'rest_api':

+ 120 - 0
Tests/test_tts_module.py

@@ -0,0 +1,120 @@
+import unittest
+import mock
+import os
+
+from core.TTS.TTSModule import TTSModule, TtsGenerateAudioFunctionNotFound
+from core.Models.Settings import Settings
+from core.FileManager import FileManager
+
+
+class TestTTSModule(unittest.TestCase):
+    """
+    Class to test TTSModule
+    """
+
+    def setUp(self):
+        self.TTSMod = TTSModule(language='tests')
+        pass
+
+    def test_generate_md5_from_words(self):
+        """
+        Test generate md5 method
+        """
+
+        word = "kalliope"
+        expected_result = "5c186d1e123be2667fb5fd54640e4fd0"
+
+        self.assertEquals(TTSModule.generate_md5_from_words(words=word),
+                          expected_result,
+                          "Fail md5")
+
+    def test_get_path_to_store_audio(self):
+        """
+        Test the path to store audio
+        """
+
+        self.TTSMod.words = "kalliope"
+        settings = Settings(cache_path="/tmp/kalliope/tests")
+        self.TTSMod.settings = settings
+
+        expected_result = "/tmp/kalliope/tests/TTSModule/tests/default/5c186d1e123be2667fb5fd54640e4fd0.tts"
+
+        self.assertEquals(self.TTSMod._get_path_to_store_audio(),
+                          expected_result,
+                          "fail test_get_path_to_store_audio, expected path not corresponding to result")
+
+    def test_generate_and_play(self):
+        """
+        Test to generate and play sound
+        """
+        def new_play_audio(TTSModule):
+            pass
+
+        words = "kalliope"
+
+        with mock.patch.object(TTSModule, 'play_audio', new=new_play_audio):
+            settings = Settings(cache_path="/tmp/kalliope/tests")
+            self.TTSMod.settings = settings
+
+            # test missing callback
+            with self.assertRaises(TtsGenerateAudioFunctionNotFound):
+                self.assertRaises(self.TTSMod.generate_and_play(words=words))
+
+            # Assert Callback is called
+            # no Cache
+            self.TTSMod.cache = False
+            generate_audio_function_from_child = mock.Mock()
+            self.TTSMod.generate_and_play(words=words,
+                                          generate_audio_function_from_child=generate_audio_function_from_child)
+            generate_audio_function_from_child.assert_called()
+
+            # with cache True but not existing on system
+            self.TTSMod.cache = True
+            generate_audio_function_from_child = mock.Mock()
+            self.TTSMod.generate_and_play(words=words,
+                                          generate_audio_function_from_child=generate_audio_function_from_child)
+            generate_audio_function_from_child.assert_called()
+
+            # with cache True and existing on system
+            # create tmp file
+            tmp_base_path = "/tmp/kalliope/tests/TTSModule/tests/default/"
+            file_path = os.path.join(tmp_base_path, "5c186d1e123be2667fb5fd54640e4fd0.tts")
+            if not os.path.exists(tmp_base_path):
+                os.makedirs(tmp_base_path)
+            FileManager.write_in_file(file_path, "[kalliope-test] test_generate_and_play")
+            self.TTSMod.cache = True
+            generate_audio_function_from_child = mock.Mock()
+            self.TTSMod.generate_and_play(words=words,
+                                          generate_audio_function_from_child=generate_audio_function_from_child)
+            generate_audio_function_from_child.assert_not_called()
+            # Remove the tmp file
+            FileManager.remove_file(file_path)
+
+    def test_is_file_already_in_cache(self):
+        """
+        Test if file is already stored in cache
+        """
+
+        base_cache_path = "/tmp/kalliope/tests/TTSModule/tests/default/"
+        md5_word = "5c186d1e123be2667fb5fd54640e4fd0"
+        file_path = "/tmp/kalliope/tests/TTSModule/tests/default/5c186d1e123be2667fb5fd54640e4fd0.tts"
+
+        # Create a tmp file
+        if not os.path.exists(base_cache_path):
+            os.makedirs(base_cache_path)
+        tmp_path = os.path.join(base_cache_path, md5_word+".tts")
+        FileManager.write_in_file(tmp_path, "[kalliope-test] test_is_file_already_in_cache")
+
+        # Test true
+        self.assertTrue(TTSModule._is_file_already_in_cache(base_cache_path=base_cache_path, file_path=file_path),
+                        "Fail retrieving the cached file. The file does not exist but it should !")
+
+        # Remove the tmp file
+        FileManager.remove_file(tmp_path)
+
+        # Test False
+        self.assertFalse(TTSModule._is_file_already_in_cache(base_cache_path=base_cache_path, file_path=file_path),
+                         "Fail asserting that the file does not exist.")
+
+if __name__ == '__main__':
+    unittest.main()

+ 1 - 1
core/Tests/test_yaml_loader.py → Tests/test_yaml_loader.py

@@ -13,7 +13,7 @@ class TestYAMLLoader(unittest.TestCase):
 
     def test_get_config(self):
 
-        valid_file_path_to_test = "core/Tests/brains/brain_test.yml"
+        valid_file_path_to_test = "Tests/brains/brain_test.yml"
         invalid_file_path = "brains/non_existing_brain.yml"
         expected_result = [
             {'signals': [{'order': 'test_order'}],

+ 14 - 3
core/RestAPI/FlaskAPI.py

@@ -27,6 +27,7 @@ class FlaskAPI(threading.Thread):
         self.app.add_url_rule('/synapses/<synapse_name>', view_func=self.get_synapse, methods=['GET'])
         self.app.add_url_rule('/synapses/<synapse_name>', view_func=self.run_synapse, methods=['POST'])
         self.app.add_url_rule('/order/', view_func=self.run_order, methods=['POST'])
+        self.app.add_url_rule('/shutdown/', view_func=self.shutdown_server, methods=['POST'])
 
     def run(self):
         self.app.run(host='0.0.0.0', port="%s" % int(self.port), debug=True, threaded=True, use_reloader=False)
@@ -39,9 +40,11 @@ class FlaskAPI(threading.Thread):
         """
         all_synapse = self.brain.brain_yaml
         for el in all_synapse:
-            print el
-            if el[0]["name"] in synapse_name:
-                return el[0]
+            try:
+                if el["name"] == synapse_name:
+                    return el
+            except KeyError:
+                pass
         return None
 
     @requires_auth
@@ -126,3 +129,11 @@ class FlaskAPI(threading.Thread):
                 "error": "order cannot be null"
             }
             return jsonify(error=data), 400
+
+    @requires_auth
+    def shutdown_server(self):
+        func = request.environ.get('werkzeug.server.shutdown')
+        if func is None:
+            raise RuntimeError('Not running with the Werkzeug Server')
+        func()
+        return "Shutting down..."

+ 10 - 9
core/TTS/TTSModule.py

@@ -64,9 +64,9 @@ class TTSModule(object):
         FileManager.create_directory(base_path)
 
         logger.debug("Class TTSModule called from module %s, cache: %s, language: %s, voice: %s" % (self.tts_caller_name,
-                                                                                             self.cache,
-                                                                                             self.language,
-                                                                                             self.voice))
+                                                                                                     self.cache,
+                                                                                                     self.language,
+                                                                                                     self.voice))
 
     def play_audio(self):
         """
@@ -96,7 +96,7 @@ class TTSModule(object):
             generate_audio_function_from_child()
         else:
             # we check if the file already exist. If not we generate it with the TTS engine
-            if not self.is_file_already_in_cache():
+            if not self._is_file_already_in_cache(self.base_cache_path, self.file_path):
                 generate_audio_function_from_child()
 
         # then play the generated audio file
@@ -136,18 +136,19 @@ class TTSModule(object):
             words = words.encode('utf-8')
         return hashlib.md5(words).hexdigest()
 
-    def is_file_already_in_cache(self):
+    @staticmethod
+    def _is_file_already_in_cache(base_cache_path, file_path):
         """
         Return true if the file to generate has already been generated before
         """
         # generate sub folder
-        FileManager.create_directory(self.base_cache_path)
+        FileManager.create_directory(base_cache_path)
 
         # check if the audio file exist
-        exist_in_cache = os.path.exists(self.file_path)
+        exist_in_cache = os.path.exists(file_path)
 
         if exist_in_cache:
-            logger.debug("TTSModule, File already in cache: %s" % self.file_path)
+            logger.debug("TTSModule, File already in cache: %s" % file_path)
         else:
-            logger.debug("TTSModule, File not yet in cache: %s" % self.file_path)
+            logger.debug("TTSModule, File not yet in cache: %s" % file_path)
         return exist_in_cache

+ 24 - 0
install/files/deb-packages_requirements.txt

@@ -0,0 +1,24 @@
+python-pip
+libssl-dev
+libportaudio0
+libportaudio2
+libportaudiocpp0
+portaudio19-dev
+libffi-dev
+python-yaml
+python-pycparser
+python-paramiko
+python-markupsafe
+apt-transport-https
+python-pip
+python-dev
+libsmpeg0
+libttspico-utils
+libsmpeg0
+flac
+dialog
+portaudio19-dev
+build-essential
+sox
+libatlas3-base
+mplayer

+ 1 - 0
install/files/python_requirements.txt

@@ -17,3 +17,4 @@ Flask-Restful==0.3.5
 wikipedia==1.4.0
 requests==2.12.1
 httpretty==0.8.14
+mock==2.0.0

+ 3 - 0
install/files/travis_repo_trusty_requirements.txt

@@ -0,0 +1,3 @@
+"deb http://archive.ubuntu.com/ubuntu trusty main restricted universe multiverse"
+"deb http://archive.ubuntu.com/ubuntu trusty-updates main restricted universe multiverse"
+"deb http://archive.ubuntu.com/ubuntu trusty-backports main restricted universe multiverse"

+ 0 - 2
install/install.yml

@@ -37,8 +37,6 @@
         - libssl-dev
         - portaudio19-dev
         - build-essential
-        - libssl-dev
-        - libffi-dev
         - sox
         - libatlas3-base
         - mplayer

+ 0 - 0
neurons/ansible_playbook/tests/__init__.py


+ 31 - 0
neurons/ansible_playbook/tests/test_ansible_playbook.py

@@ -0,0 +1,31 @@
+import unittest
+
+from core.NeuronModule import MissingParameterException
+from neurons.ansible_playbook.ansible_playbook import Ansible_playbook
+
+
+class TestAnsible_Playbook(unittest.TestCase):
+
+    def setUp(self):
+        self.task_file="task_file"
+        self.random = "random"
+
+    def testParameters(self):
+        def run_test(parameters_to_test):
+            with self.assertRaises(MissingParameterException):
+                Ansible_playbook(**parameters_to_test)
+
+        # empty
+        parameters = dict()
+        run_test(parameters)
+
+        # missing task_file
+        parameters = {
+            "random": self.random
+        }
+        run_test(parameters)
+
+
+if __name__ == '__main__':
+    unittest.main()
+

+ 0 - 0
neurons/gmail_checker/tests/__init__.py


+ 37 - 0
neurons/gmail_checker/tests/test_gmail_checker.py

@@ -0,0 +1,37 @@
+import unittest
+
+from core.NeuronModule import MissingParameterException
+from neurons.gmail_checker.gmail_checker import Gmail_checker
+
+
+class TestGmail_Checker(unittest.TestCase):
+
+    def setUp(self):
+        self.username="username"
+        self.password="password"
+
+    def testParameters(self):
+        def run_test(parameters_to_test):
+            with self.assertRaises(MissingParameterException):
+                Gmail_checker(**parameters_to_test)
+
+        # empty
+        parameters = dict()
+        run_test(parameters)
+
+        # missing password
+        parameters = {
+            "username": self.username
+        }
+        run_test(parameters)
+
+        # missing username
+        parameters = {
+           "password": self.password
+        }
+        run_test(parameters)
+
+
+if __name__ == '__main__':
+    unittest.main()
+

+ 4 - 4
neurons/openweathermap/openweathermap.py

@@ -1,6 +1,6 @@
 import pyowm
 
-from core.NeuronModule import NeuronModule
+from core.NeuronModule import NeuronModule, MissingParameterException
 
 
 class Openweathermap(NeuronModule):
@@ -120,8 +120,8 @@ class Openweathermap(NeuronModule):
         .. raises:: NotImplementedError
         """
         if self.api_key is None:
-            raise NotImplementedError("OpenWeatherMap neuron needs an api_key")
+            raise MissingParameterException("OpenWeatherMap neuron needs an api_key")
         if self.location is None:
-            raise NotImplementedError("OpenWeatherMap neuron needs a location")
+            raise MissingParameterException("OpenWeatherMap neuron needs a location")
 
-        return True
+        return True

+ 0 - 0
neurons/openweathermap/tests/__init__.py


+ 36 - 0
neurons/openweathermap/tests/test_openweathermap.py

@@ -0,0 +1,36 @@
+import unittest
+
+from core.NeuronModule import MissingParameterException
+from neurons.openweathermap.openweathermap import Openweathermap
+
+
+class TestOpenWeatherMap(unittest.TestCase):
+
+    def setUp(self):
+        self.location="location"
+        self.api_key="api_key"
+
+    def testParameters(self):
+        def run_test(parameters_to_test):
+            with self.assertRaises(MissingParameterException):
+                Openweathermap(**parameters_to_test)
+
+        # empty
+        parameters = dict()
+        run_test(parameters)
+
+        # missing api_key
+        parameters = {
+            "location": self.location
+        }
+        run_test(parameters)
+
+        # missing location
+        parameters = {
+           "api_key": self.api_key
+        }
+        run_test(parameters)
+
+
+if __name__ == '__main__':
+    unittest.main()

+ 4 - 4
neurons/push_message/push_message.py

@@ -1,7 +1,7 @@
 from __future__ import absolute_import
 from pushetta import Pushetta
 
-from core.NeuronModule import NeuronModule
+from core.NeuronModule import NeuronModule, MissingParameterException
 
 
 class Push_message(NeuronModule):
@@ -34,10 +34,10 @@ class Push_message(NeuronModule):
         .. raises:: NotImplementedError
         """
         if self.message is None:
-            raise NotImplementedError("Pushetta neuron needs message to send")
+            raise MissingParameterException("Pushetta neuron needs message to send")
         if self.api_key is None:
-            raise NotImplementedError("Pushetta neuron needs api_key")
+            raise MissingParameterException("Pushetta neuron needs api_key")
         if self.channel_name is None:
-            raise NotImplementedError("Pushetta neuron needs channel_name")
+            raise MissingParameterException("Pushetta neuron needs channel_name")
 
         return True

+ 0 - 0
neurons/push_message/tests/__init__.py


+ 46 - 0
neurons/push_message/tests/test_push_message.py

@@ -0,0 +1,46 @@
+import unittest
+
+from core.NeuronModule import MissingParameterException
+from neurons.push_message.push_message import Push_message
+
+
+class TestPush_Message(unittest.TestCase):
+
+    def setUp(self):
+        self.message="message"
+        self.api_key="api_key"
+        self.channel_name = "channel_name"
+
+    def testParameters(self):
+        def run_test(parameters_to_test):
+            with self.assertRaises(MissingParameterException):
+                Push_message(**parameters_to_test)
+
+        # empty
+        parameters = dict()
+        run_test(parameters)
+
+        # missing api_key
+        parameters = {
+            "message": self.message,
+            "channel_name": self.channel_name
+        }
+        run_test(parameters)
+
+        # missing channel_name
+        parameters = {
+           "api_key": self.api_key,
+            "message":self.message
+        }
+        run_test(parameters)
+
+        # missing message
+        parameters = {
+            "api_key": self.api_key,
+            "channel_name": self.channel_name
+        }
+        run_test(parameters)
+
+
+if __name__ == '__main__':
+    unittest.main()

+ 0 - 0
neurons/say/tests/__init__.py


+ 27 - 0
neurons/say/tests/test_say.py

@@ -0,0 +1,27 @@
+import unittest
+
+from core.NeuronModule import MissingParameterException
+from neurons.say.say import Say
+
+
+class TestSay(unittest.TestCase):
+
+    def setUp(self):
+        self.message="message"
+        self.random = "random"
+
+    def testParameters(self):
+        def run_test(parameters_to_test):
+            with self.assertRaises(MissingParameterException):
+                Say(**parameters_to_test)
+
+        # empty
+        parameters = dict()
+        run_test(parameters)
+
+        # missing message
+        parameters = {
+            "random": self.random
+        }
+        run_test(parameters)
+

+ 0 - 0
neurons/script/tests/__init__.py


+ 61 - 0
neurons/script/tests/test_script.py

@@ -0,0 +1,61 @@
+import unittest
+import os
+
+from core.NeuronModule import MissingParameterException, InvalidParameterException
+from neurons.script.script import Script
+from core.FileManager import FileManager
+
+
+class TestScript(unittest.TestCase):
+
+    def setUp(self):
+        self.path = "path"
+        self.random = "random"
+
+    def testParameters(self):
+        def run_test_missing_param(parameters_to_test):
+            with self.assertRaises(MissingParameterException):
+                Script(**parameters_to_test)
+
+        def run_test_invalid_param(parameters_to_test):
+            with self.assertRaises(InvalidParameterException):
+                Script(**parameters_to_test)
+
+        # empty
+        parameters = dict()
+        run_test_missing_param(parameters)
+
+        # missing path
+        parameters = {
+            "random": self.random
+        }
+        run_test_missing_param(parameters)
+
+        # random path
+        self.path = "/tmp/iamarandompath/anotherrandompath/kalliope"
+        parameters = {
+            "path": self.path
+        }
+        run_test_invalid_param(parameters)
+
+        # Test Non executable file
+        # Create the file and remove permissions to the user
+        tmp_path = "/tmp/kalliope/tests/"
+        tmp_file_path = tmp_path+"neuronScript"
+        if not os.path.exists(tmp_path):
+            os.makedirs(tmp_path)
+        FileManager.write_in_file(tmp_file_path, "[kalliope-test] TestScript - testParameters")
+        os.chmod(tmp_file_path, 0600)
+        # test the user does not have access
+        self.path = tmp_file_path
+        parameters = {
+            "path": self.path
+        }
+        run_test_invalid_param(parameters)
+        # Remove the tmp file
+        os.chmod(tmp_file_path, 0700)
+        FileManager.remove_file(tmp_file_path)
+
+
+if __name__ == '__main__':
+    unittest.main()

+ 0 - 0
neurons/shell/tests/__init__.py


+ 30 - 0
neurons/shell/tests/test_shell.py

@@ -0,0 +1,30 @@
+import unittest
+
+from core.NeuronModule import MissingParameterException
+from neurons.shell.shell import Shell
+
+
+class TestShell(unittest.TestCase):
+
+    def setUp(self):
+        self.cmd="cmd"
+        self.random="random"
+
+    def testParameters(self):
+        def run_test(parameters_to_test):
+            with self.assertRaises(MissingParameterException):
+                Shell(**parameters_to_test)
+
+        # empty
+        parameters = dict()
+        run_test(parameters)
+
+        # missing cmd
+        parameters = {
+            "random": self.random
+        }
+        run_test(parameters)
+
+
+if __name__ == '__main__':
+    unittest.main()

+ 0 - 0
neurons/sleep/tests/__init__.py


+ 30 - 0
neurons/sleep/tests/test_sleep.py

@@ -0,0 +1,30 @@
+import unittest
+
+from core.NeuronModule import MissingParameterException
+from neurons.sleep.sleep import Sleep
+
+
+class TestSleep(unittest.TestCase):
+
+    def setUp(self):
+        self.second="second"
+        self.random="random"
+
+    def testParameters(self):
+        def run_test(parameters_to_test):
+            with self.assertRaises(MissingParameterException):
+                Sleep(**parameters_to_test)
+
+        # empty
+        parameters = dict()
+        run_test(parameters)
+
+        # missing second
+        parameters = {
+            "random": self.random
+        }
+        run_test(parameters)
+
+
+if __name__ == '__main__':
+    unittest.main()

+ 0 - 0
neurons/tasker_autoremote/tests/__init__.py


+ 36 - 0
neurons/tasker_autoremote/tests/test_tasker_autoremote.py

@@ -0,0 +1,36 @@
+import unittest
+
+from core.NeuronModule import MissingParameterException
+from neurons.sleep.sleep import Sleep
+
+
+class TestSleep(unittest.TestCase):
+
+    def setUp(self):
+        self.key="key"
+        self.message="message"
+
+    def testParameters(self):
+        def run_test(parameters_to_test):
+            with self.assertRaises(MissingParameterException):
+                Sleep(**parameters_to_test)
+
+        # empty
+        parameters = dict()
+        run_test(parameters)
+
+        # missing key
+        parameters = {
+            "message": self.message
+        }
+        run_test(parameters)
+
+        # missing message
+        parameters = {
+            "key": self.key
+        }
+        run_test(parameters)
+
+
+if __name__ == '__main__':
+    unittest.main()

+ 0 - 0
neurons/twitter/tests/__init__.py


+ 68 - 0
neurons/twitter/tests/test_twitter_neuron.py

@@ -0,0 +1,68 @@
+import unittest
+
+from core.NeuronModule import MissingParameterException
+from neurons.twitter.twitter import Twitter
+
+
+class TestTwitter(unittest.TestCase):
+
+    def setUp(self):
+        self.consumer_key="kalliokey"
+        self.consumer_secret = "kalliosecret"
+        self.access_token_key = "kalliotokenkey"
+        self.access_token_secret = "kalliotokensecret"
+        self.tweet = "kalliotweet"
+
+    def testParameters(self):
+        def run_test(parameters_to_test):
+            with self.assertRaises(MissingParameterException):
+                Twitter(**parameters_to_test)
+
+        # empty
+        parameters = dict()
+        run_test(parameters)
+
+        # missing tweet
+        parameters = {
+            "consumer_key": self.consumer_key,
+            "consumer_secret": self.consumer_secret,
+            "access_token_key": self.access_token_key,
+            "access_token_secret": self.access_token_secret
+        }
+        run_test(parameters)
+
+        # missing consumer_key
+        parameters = {
+            "consumer_secret": self.consumer_secret,
+            "access_token_key": self.access_token_key,
+            "access_token_secret": self.access_token_secret,
+            "tweet": self.tweet
+        }
+        run_test(parameters)
+
+        # missing consumer_secret
+        parameters = {
+            "consumer_key": self.consumer_key,
+            "access_token_key": self.access_token_key,
+            "access_token_secret": self.access_token_secret,
+            "tweet": self.tweet
+        }
+        run_test(parameters)
+
+        # missing access_token_key
+        parameters = {
+            "consumer_key": self.consumer_key,
+            "consumer_secret": self.consumer_secret,
+            "access_token_secret": self.access_token_secret,
+            "tweet": self.tweet
+        }
+        run_test(parameters)
+
+        # missing access_token_secret
+        parameters = {
+            "consumer_key": self.consumer_key,
+            "consumer_secret": self.consumer_secret,
+            "access_token_key": self.access_token_key,
+            "tweet": self.tweet
+        }
+        run_test(parameters)

+ 6 - 6
neurons/twitter/twitter.py

@@ -1,6 +1,6 @@
 import twitter
 
-from core.NeuronModule import NeuronModule, InvalidParameterException
+from core.NeuronModule import NeuronModule, InvalidParameterException, MissingParameterException
 
 
 class Twitter(NeuronModule):
@@ -36,15 +36,15 @@ class Twitter(NeuronModule):
         .. raises:: InvalidParameterException
         """
         if self.consumer_key is None:
-            raise InvalidParameterException("Twitter needs a consumer_key")
+            raise MissingParameterException("Twitter needs a consumer_key")
         if self.consumer_secret is None:
-            raise InvalidParameterException("Twitter needs a consumer_secret")
+            raise MissingParameterException("Twitter needs a consumer_secret")
         if self.access_token_key is None:
-            raise InvalidParameterException("Twitter needs an access_token_key")
+            raise MissingParameterException("Twitter needs an access_token_key")
         if self.access_token_secret is None:
-            raise InvalidParameterException("Twitter needs and access_token_secret")
+            raise MissingParameterException("Twitter needs and access_token_secret")
         if self.tweet is None:
-            raise InvalidParameterException("You need to provide something to tweet !")
+            raise MissingParameterException("You need to provide something to tweet !")
 
         return True
 

+ 0 - 0
neurons/wake_on_lan/tests/__init__.py


+ 67 - 0
neurons/wake_on_lan/tests/test_wake_on_lan.py

@@ -0,0 +1,67 @@
+import unittest
+import ipaddress
+
+from core.NeuronModule import InvalidParameterException, MissingParameterException
+from neurons.wake_on_lan.wake_on_lan import Wake_on_lan
+
+
+class TestWakeOnLan(unittest.TestCase):
+
+    def setUp(self):
+        self.mac_address="00:0a:95:9d:68:16"
+        self.broadcast_address = "255.255.255.255"
+        self.port = 42
+
+    def testParameters(self):
+        def run_test_invalidParam(parameters_to_test):
+            with self.assertRaises(InvalidParameterException):
+                Wake_on_lan(**parameters_to_test)
+
+        def run_test_missingParam(parameters_to_test):
+            with self.assertRaises(MissingParameterException):
+                Wake_on_lan(**parameters_to_test)
+
+        def run_test_valueError(parameters_to_test):
+            with self.assertRaises(ValueError):
+                Wake_on_lan(**parameters_to_test)
+
+        # empty
+        parameters = dict()
+        run_test_missingParam(parameters)
+
+        # missing mac_address
+        parameters = {
+            "broadcast_address": self.broadcast_address,
+            "port": self.port
+        }
+        run_test_missingParam(parameters)
+
+        # port is not an int
+        self.port = "port"
+        parameters = {
+            "broadcast_address": self.broadcast_address,
+            "mac_address": self.mac_address,
+            "port": self.port
+        }
+        run_test_invalidParam(parameters)
+        self.port = 42
+
+        # is broadcast not a valid format
+        self.broadcast_address = "broadcast"
+        parameters = {
+            "broadcast_address": self.broadcast_address,
+            "mac_address": self.mac_address,
+            "port": self.port
+        }
+        run_test_valueError(parameters)
+        self.broadcast_address = "255.255.255.255"
+
+        # is mac_address not a valid IPv4 or IPv6 format
+        self.mac_address = "mac_address"
+        parameters = {
+            "broadcast_address": self.broadcast_address,
+            "mac_address": self.mac_address,
+            "port": self.port
+        }
+        run_test_valueError(parameters)
+        self.mac_address = "00:0a:95:9d:68:16"