# This file is part of TALER # (C) 2019 Taler Systems SA # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 3 of the License, or (at your option) any later # version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free # Software Foundation, Inc., 51 Franklin Street, Fifth Floor, # Boston, MA 02110-1301 USA # # @author Marcello Stanisci # @version 0.0 # @repository https://git.taler.net/taler-util.git/ from unittest import TestCase from taler.util.gnunet_log import GnunetLogger as GL import os from mock import patch, MagicMock import logging from datetime import datetime # How the logging module defines loglevels. # # ERROR = 40 # WARNING = 30 # INFO = 20 # DEBUG = 10 ## # Helper function that removes any logging definition from the # environment. def clean_env(): if os.environ.get("GNUNET_FORCE_LOG"): del os.environ["GNUNET_FORCE_LOG"] if os.environ.get("GNUNET_LOG"): del os.environ["GNUNET_LOG"] if os.environ.get("GNUNET_FORCE_LOGFILE"): del os.environ["GNUNET_FORCE_LOGFILE"] ## # "mother" class of all the tests. NOTE: no logs will appear # on screen, as the setLevel function is mocked (therefore the # level specified won't be made effective -- rather, only the # default level (WARNING) will apply)! class TestGnunetLog(TestCase): ## # Setup method; just take care of cleaning the environment. def setUp(self): clean_env() ## # This function tests whether GNUNET_FORCE_LOGFILE # is correctly interpreted. # # @param self the object itself. # @param mocked_FileHandler "mock" object that will # "pretend" to be the file handler where the # logging logic will register the logfile path. # @param mocked_addHandler "mock" object on which the # logging logic is expected to register the @a # mocked_FileHandler. @patch("logging.Logger.addHandler") @patch("logging.FileHandler") def test_force_logfile(self, mocked_FileHandler, mocked_addHandler): os.environ["GNUNET_FORCE_LOGFILE"] = "/tmp/{}-[]-%Y_%m_%d.log" unused_mock = MagicMock() mocked_FileHandler.return_value = unused_mock gl = GL("gnunet-pylog") gl.log("msg", gl.DEBUG) today = datetime.now() expected_filename = "/tmp/gnunet-pylog-%s-%s.log" % ( str(os.getpid()), today.strftime("%Y_%m_%d"), ) mocked_FileHandler.assert_called_with(expected_filename) mocked_addHandler.assert_called_with(unused_mock) ## # This function tests the very basic case, where no # env variable is set and no explicit loglevel is given # via the "setup()" method. The expected result is that # the level is set to INFO. # # @param self the object itself. # @param mocked_basicConfig "mock" object that substitutes # the real basicConfig. # @param mocked_setLevel "mock" object that substitutes # the real setLevel. @patch("logging.Logger.setLevel") @patch("logging.basicConfig") def test_no_env_and_no_setup(self, mocked_basicConfig, mocked_setLevel): # Double-check no env variable gets in the way. self.assertIsNone(os.environ.get("GNUNET_FORCE_LOG")) self.assertIsNone(os.environ.get("GNUNET_LOG")) gl = GL("gnunet-pylog") gl.log("msg", gl.DEBUG) mocked_setLevel.assert_called_with(level=logging.INFO) ## # This function tests the case where *only* the GNUNET_LOG # env variable is set -- not even the manual setup of the # loglevel - via a call to the "setup()" method - is put in place. # # @param self the object itself. # @param mocked_basicConfig "mock" object that substitutes # the real basicConfig. # @param mocked_setLevel "mock" object that substitutes # the real setLevel. @patch("logging.Logger.setLevel") @patch("logging.basicConfig") def test_non_forced_env(self, mocked_basicConfig, mocked_setLevel): self.assertIsNone(os.environ.get("GNUNET_FORCE_LOG")) os.environ[ "GNUNET_LOG" ] = "gnunet-pylog;log_test.py;test_non_forced_env;99;ERROR" # lineno is not 100% accurate. gl = GL("gnunet-pylog") gl.log("msg", gl.DEBUG) mocked_setLevel.assert_called_with(level=logging.INFO) ## # This function tests the case where *only* the GNUNET_FORCE_LOG # env variable is set -- not even the manual setup of the loglevel # is put in place. # # @param self the object itself. # @param mocked_basicConfig "mock" object that substitutes # the real basicConfig. # @param mocked_setLevel "mock" object that substitutes # the real setLevel. @patch("logging.Logger.setLevel") @patch("logging.basicConfig") def test_only_forced_env(self, mocked_basicConfig, mocked_setLevel): self.assertIsNone(os.environ.get("GNUNET_LOG")) os.environ[ "GNUNET_FORCE_LOG" ] = "gnunet-pylog;log_test.py;test_only_forced_env;90-200;ERROR" gl = GL("gnunet-pylog") gl.log("msg", gl.DEBUG) mocked_setLevel.assert_called_with(level=logging.INFO) ## # This function tests the case where *only* the manual # loglevel setup is put in place. # # @param self the object itself. # @param mocked_basicConfig "mock" object that substitutes # the real basicConfig. # @param mocked_setLevel "mock" object that substitutes # the real setLevel. @patch("logging.Logger.setLevel") @patch("logging.basicConfig") def test_only_manual_loglevel_setup(self, mocked_basicConfig, mocked_setLevel): self.assertIsNone(os.environ.get("GNUNET_LOG")) self.assertIsNone(os.environ.get("GNUNET_FORCE_LOG")) gl = GL("gnunet-pylog") gl.setup(gl.ERROR) gl.log("msg", gl.DEBUG) mocked_setLevel.assert_called_with(level=logging.ERROR) ## # This function tests the case where *both* the manual loglevel # and the forced env variable are setup; the expected result is # that the forced variable wins over the manual setup. # # @param self the object itself. # @param mocked_basicConfig "mock" object that substitutes # the real basicConfig. # @param mocked_setLevel "mock" object that substitutes # the real setLevel. @patch("logging.Logger.setLevel") @patch("logging.basicConfig") def test_manual_loglevel_AND_forced_env(self, mocked_basicConfig, mocked_setLevel): self.assertIsNone(os.environ.get("GNUNET_LOG")) self.assertIsNone(os.environ.get("GNUNET_FORCE_LOG")) # forced env definition (*before* object creation) os.environ["GNUNET_FORCE_LOG"] = ";;;;ERROR" gl = GL("gnunet-pylog") # manual setup gl.setup(gl.WARNING) gl.log("msg", gl.DEBUG) mocked_setLevel.assert_called_with(level=logging.ERROR) ## # This function tests the case where *both* GNUNET_LOG and # the manual loglevel setup are put in place. The expectation # is that the manual loglevel wins. # # @param self the object itself. # @param mocked_basicConfig "mock" object that substitutes # the real basicConfig. # @param mocked_setLevel "mock" object that substitutes # the real setLevel. @patch("logging.Logger.setLevel") @patch("logging.basicConfig") def test_manual_loglevel_AND_nonforced_env( self, mocked_basicConfig, mocked_setLevel ): self.assertIsNone(os.environ.get("GNUNET_LOG")) self.assertIsNone(os.environ.get("GNUNET_FORCE_LOG")) os.environ["GNUNET_LOG"] = ";;;;DEBUG" gl = GL("gnunet-pylog") gl.setup(gl.ERROR) gl.log("msg", gl.DEBUG) mocked_setLevel.assert_called_with(level=logging.ERROR) ## # This function tests the case where *both* GNUNET_LOG and # GNUNET_FORCE_LOG are defined. The expectation is that the # forced variable wins. # # @param self the object itself. # @param mocked_basicConfig "mock" object that substitutes # the real basicConfig. # @param mocked_setLevel "mock" object that substitutes # the real setLevel. @patch("logging.Logger.setLevel") @patch("logging.basicConfig") def test_forced_env_AND_nonforced_env(self, mocked_basicConfig, mocked_setLevel): self.assertIsNone(os.environ.get("GNUNET_LOG")) self.assertIsNone(os.environ.get("GNUNET_FORCE_LOG")) os.environ["GNUNET_LOG"] = ";;;;DEBUG" os.environ["GNUNET_FORCE_LOG"] = ";;;;ERROR" gl = GL("gnunet-pylog") gl.log("msg", gl.DEBUG) mocked_setLevel.assert_called_with(level=logging.ERROR)