From 57b3a9e6b836b33201cf4e2630fd228032e657e4 Mon Sep 17 00:00:00 2001 From: Benoit HERARD Date: Thu, 27 Apr 2017 11:23:00 +0200 Subject: Add Energy recording support It adds helpers to send notifications to Energy recording API and related unit tests. It requires a dedicated section in functest config file to set connectivity parameters to Energy recording API. It is using shared API Recording at http://161.105.253.100:8888 Change-Id: Idcb74d1bf7341ccce7cc1c3926f22338ce24f714 Signed-off-by: Benoit HERARD --- functest/tests/unit/energy/test_functest_energy.py | 277 +++++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 functest/tests/unit/energy/test_functest_energy.py (limited to 'functest/tests/unit/energy/test_functest_energy.py') diff --git a/functest/tests/unit/energy/test_functest_energy.py b/functest/tests/unit/energy/test_functest_energy.py new file mode 100644 index 000000000..ffe044bc2 --- /dev/null +++ b/functest/tests/unit/energy/test_functest_energy.py @@ -0,0 +1,277 @@ +#!/usr/bin/env python + +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + +"""Unitary test for energy module.""" +# pylint: disable=unused-argument +import logging +import unittest + +import mock + +from functest.energy.energy import EnergyRecorder +import functest.energy.energy as energy + + +CASE_NAME = "UNIT_test_CASE" +STEP_NAME = "UNIT_test_STEP" + +logging.disable(logging.CRITICAL) + + +class MockHttpResponse(object): # pylint: disable=too-few-public-methods + """Mock response for Energy recorder API.""" + + def __init__(self, text, status_code): + """Create an instance of MockHttpResponse.""" + self.text = text + self.status_code = status_code + + +RECORDER_OK = MockHttpResponse( + '{"environment": "UNIT_TEST",' + ' "step": "string",' + ' "scenario": "' + CASE_NAME + '"}', + 200 +) +RECORDER_KO = MockHttpResponse( + '{"message": "An unhandled API exception occurred (MOCK)"}', + 500 +) + + +def config_loader_mock(config_key): + """Return mocked config values.""" + if config_key == "energy_recorder.api_url": + return "http://pod-uri:8888" + elif config_key == "energy_recorder.api_user": + return "user" + elif config_key == "energy_recorder.api_password": + return "password" + else: + raise Exception("Config not mocked") + + +def config_loader_mock_no_creds(config_key): + """Return mocked config values.""" + if config_key == "energy_recorder.api_url": + return "http://pod-uri:8888" + elif config_key == "energy_recorder.api_user": + return "" + elif config_key == "energy_recorder.api_password": + return "" + else: + raise Exception("Config not mocked:" + config_key) + + +class EnergyRecorderTest(unittest.TestCase): + """Energy module unitary test suite.""" + + case_name = CASE_NAME + request_headers = {'content-type': 'application/json'} + returned_value_to_preserve = "value" + exception_message_to_preserve = "exception_message" + + @mock.patch('functest.energy.energy.requests.post', + return_value=RECORDER_OK) + def test_start(self, post_mock=None): + """EnergyRecorder.start method (regular case).""" + self.test_load_config() + self.assertTrue(EnergyRecorder.start(self.case_name)) + post_mock.assert_called_once_with( + EnergyRecorder.energy_recorder_api["uri"], + auth=EnergyRecorder.energy_recorder_api["auth"], + data=mock.ANY, + headers=self.request_headers + ) + + @mock.patch('functest.energy.energy.requests.post', + side_effect=Exception("Internal execution error (MOCK)")) + def test_start_error(self, post_mock=None): + """EnergyRecorder.start method (error in method).""" + self.test_load_config() + self.assertFalse(EnergyRecorder.start(self.case_name)) + post_mock.assert_called_once_with( + EnergyRecorder.energy_recorder_api["uri"], + auth=EnergyRecorder.energy_recorder_api["auth"], + data=mock.ANY, + headers=self.request_headers + ) + + @mock.patch('functest.energy.energy.requests.post', + return_value=RECORDER_KO) + def test_start_api_error(self, post_mock=None): + """EnergyRecorder.start method (API error).""" + self.test_load_config() + self.assertFalse(EnergyRecorder.start(self.case_name)) + post_mock.assert_called_once_with( + EnergyRecorder.energy_recorder_api["uri"], + auth=EnergyRecorder.energy_recorder_api["auth"], + data=mock.ANY, + headers=self.request_headers + ) + + @mock.patch('functest.energy.energy.requests.post', + return_value=RECORDER_OK) + def test_set_step(self, post_mock=None): + """EnergyRecorder.set_step method (regular case).""" + self.test_load_config() + self.assertTrue(EnergyRecorder.set_step(STEP_NAME)) + post_mock.assert_called_once_with( + EnergyRecorder.energy_recorder_api["uri"] + "/step", + auth=EnergyRecorder.energy_recorder_api["auth"], + data=mock.ANY, + headers=self.request_headers + ) + + @mock.patch('functest.energy.energy.requests.post', + return_value=RECORDER_KO) + def test_set_step_api_error(self, post_mock=None): + """EnergyRecorder.set_step method (API error).""" + self.test_load_config() + self.assertFalse(EnergyRecorder.set_step(STEP_NAME)) + post_mock.assert_called_once_with( + EnergyRecorder.energy_recorder_api["uri"] + "/step", + auth=EnergyRecorder.energy_recorder_api["auth"], + data=mock.ANY, + headers=self.request_headers + ) + + @mock.patch('functest.energy.energy.requests.post', + side_effect=Exception("Internal execution error (MOCK)")) + def test_set_step_error(self, post_mock=None): + """EnergyRecorder.set_step method (method error).""" + self.test_load_config() + self.assertFalse(EnergyRecorder.set_step(STEP_NAME)) + post_mock.assert_called_once_with( + EnergyRecorder.energy_recorder_api["uri"] + "/step", + auth=EnergyRecorder.energy_recorder_api["auth"], + data=mock.ANY, + headers=self.request_headers + ) + + @mock.patch('functest.energy.energy.requests.delete', + return_value=RECORDER_OK) + def test_stop(self, delete_mock=None): + """EnergyRecorder.stop method (regular case).""" + self.test_load_config() + self.assertTrue(EnergyRecorder.stop()) + delete_mock.assert_called_once_with( + EnergyRecorder.energy_recorder_api["uri"], + auth=EnergyRecorder.energy_recorder_api["auth"], + headers=self.request_headers + ) + + @mock.patch('functest.energy.energy.requests.delete', + return_value=RECORDER_KO) + def test_stop_api_error(self, delete_mock=None): + """EnergyRecorder.stop method (API Error).""" + self.test_load_config() + self.assertFalse(EnergyRecorder.stop()) + delete_mock.assert_called_once_with( + EnergyRecorder.energy_recorder_api["uri"], + auth=EnergyRecorder.energy_recorder_api["auth"], + headers=self.request_headers + ) + + @mock.patch('functest.energy.energy.requests.delete', + side_effect=Exception("Internal execution error (MOCK)")) + def test_stop_error(self, delete_mock=None): + """EnergyRecorder.stop method (method error).""" + self.test_load_config() + self.assertFalse(EnergyRecorder.stop()) + delete_mock.assert_called_once_with( + EnergyRecorder.energy_recorder_api["uri"], + auth=EnergyRecorder.energy_recorder_api["auth"], + headers=self.request_headers + ) + + @energy.enable_recording + def __decorated_method(self): + """Call with to energy recorder decorators.""" + return self.returned_value_to_preserve + + @energy.enable_recording + def __decorated_method_with_ex(self): + """Call with to energy recorder decorators.""" + raise Exception(self.exception_message_to_preserve) + + @mock.patch("functest.energy.energy.EnergyRecorder") + @mock.patch("functest.utils.functest_utils.get_pod_name", + return_value="MOCK_POD") + @mock.patch("functest.utils.functest_utils.get_functest_config", + side_effect=config_loader_mock) + def test_decorators(self, + loader_mock=None, + pod_mock=None, + recorder_mock=None): + """Test energy module decorators.""" + self.__decorated_method() + calls = [mock.call.start(self.case_name), + mock.call.stop()] + recorder_mock.assert_has_calls(calls) + + def test_decorator_preserve_return(self): + """Test that decorator preserve method returned value.""" + self.test_load_config() + self.assertTrue( + self.__decorated_method() == self.returned_value_to_preserve + ) + + def test_decorator_preserve_ex(self): + """Test that decorator preserve method exceptions.""" + self.test_load_config() + with self.assertRaises(Exception) as context: + self.__decorated_method_with_ex() + self.assertTrue( + self.exception_message_to_preserve in context.exception + ) + + @mock.patch("functest.utils.functest_utils.get_functest_config", + side_effect=config_loader_mock) + @mock.patch("functest.utils.functest_utils.get_pod_name", + return_value="MOCK_POD") + def test_load_config(self, loader_mock=None, pod_mock=None): + """Test load config.""" + EnergyRecorder.energy_recorder_api = None + EnergyRecorder.load_config() + self.assertEquals( + EnergyRecorder.energy_recorder_api["auth"], + ("user", "password") + ) + self.assertEquals( + EnergyRecorder.energy_recorder_api["uri"], + "http://pod-uri:8888/recorders/environment/MOCK_POD" + ) + + @mock.patch("functest.utils.functest_utils.get_functest_config", + side_effect=config_loader_mock_no_creds) + @mock.patch("functest.utils.functest_utils.get_pod_name", + return_value="MOCK_POD") + def test_load_config_no_creds(self, loader_mock=None, pod_mock=None): + """Test load config without creds.""" + EnergyRecorder.energy_recorder_api = None + EnergyRecorder.load_config() + self.assertEquals(EnergyRecorder.energy_recorder_api["auth"], None) + self.assertEquals( + EnergyRecorder.energy_recorder_api["uri"], + "http://pod-uri:8888/recorders/environment/MOCK_POD" + ) + + @mock.patch("functest.utils.functest_utils.get_functest_config", + return_value=None) + @mock.patch("functest.utils.functest_utils.get_pod_name", + return_value="MOCK_POD") + def test_load_config_ex(self, loader_mock=None, pod_mock=None): + """Test load config with exception.""" + with self.assertRaises(AssertionError): + EnergyRecorder.energy_recorder_api = None + EnergyRecorder.load_config() + self.assertEquals(EnergyRecorder.energy_recorder_api, None) + + +if __name__ == "__main__": + unittest.main(verbosity=2) -- cgit 1.2.3-korg