| 
 # Copyright (C) 2011  Internet Systems Consortium.  
#  
# Permission to use, copy, modify, and distribute this software for any  
# purpose with or without fee is hereby granted, provided that the above  
# copyright notice and this permission notice appear in all copies.  
#  
# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM  
# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL  
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL  
# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,  
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING  
# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,  
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  
  
# This tests it can be loaded, nothing more yet  
import isc.log  
import unittest  
import json  
import sys  
import bind10_config  
from isc.config.ccsession import path_search  
  
class LogDict(unittest.TestCase):  
    def setUp(self):  
        # We work on a test dictionary now.  
        isc.log.set_test_dictionary(True)  
    def tearDown(self):  
        # Return to the global dictionary  
        isc.log.set_test_dictionary(False)  
  
    def test_load_msgs(self):  
        # Try loading a message and see it's there, but nothing more  
        self.assertEqual(isc.log.create_message("ID", "Text"), "ID")  
        self.assertEqual(isc.log.get_message("ID"), "Text")  
        self.assertEqual(isc.log.get_message("no-ID"), None)  
  
class Manager(unittest.TestCase):  
    def tearDown(self):  
        isc.log.reset()  
  
    def test_init_debug(self):  
        # We try calling it now only, as we don't have any other functions  
        # to check the outcome by it. Once we add the logger class, we may  
        # check more.  
        isc.log.init("root", "DEBUG", 50, None)  
  
    def test_init_defaults(self):  
        # We try calling it now only, as we don't have any other functions  
        # to check the outcome by it. Once we add the logger class, we may  
        # check more.  
        isc.log.init("root")  
  
    def test_init_notfound(self):  
        # This should not throw, because the C++ one doesn't. Should we really  
        # ignore errors like missing file?  
        isc.log.init("root", "INFO", 0, "/no/such/file");  
  
    def test_log_config_update(self):  
        log_spec = json.dumps(isc.config.module_spec_from_file(path_search('logging.spec', bind10_config.PLUGIN_PATHS)).get_full_spec())  
  
        self.assertRaises(TypeError, isc.log.log_config_update)  
        self.assertRaises(TypeError, isc.log.log_config_update, 1)  
        self.assertRaises(TypeError, isc.log.log_config_update, 1, 1)  
        self.assertRaises(TypeError, isc.log.log_config_update, 1, 1, 1)  
  
        self.assertRaises(TypeError, isc.log.log_config_update, 1, log_spec)  
        self.assertRaises(TypeError, isc.log.log_config_update, [], log_spec)  
        self.assertRaises(TypeError, isc.log.log_config_update, "foo", log_spec)  
        self.assertRaises(TypeError, isc.log.log_config_update, "{ '", log_spec)  
  
        # empty should pass  
        isc.log.log_config_update("{}", log_spec)  
  
        # bad spec  
        self.assertRaises(TypeError, isc.log.log_config_update, "{}", json.dumps({"foo": "bar"}))  
  
        # Try a correct one  
        log_conf = json.dumps({"loggers":  
                                [{"name": "b10-xfrout", "output_options":  
                                    [{"output": "/tmp/bind10.log",  
                                       "destination": "file",  
                                       "flush": True}]}]})  
        isc.log.log_config_update(log_conf, log_spec)  
  
class Logger(unittest.TestCase):  
    def tearDown(self):  
        isc.log.reset()  
  
    def setUp(self):  
        isc.log.init("root", "DEBUG", 50)  
        self.sevs = ['INFO', 'WARN', 'ERROR', 'FATAL']  
        self.TEST_MSG = isc.log.create_message('TEST_MESSAGE', '%1')  
  
    # Checks defaults of the logger  
    def defaults(self, logger):  
        self.assertEqual(logger.get_effective_severity(), "DEBUG")  
        self.assertEqual(logger.get_effective_debug_level(), 50)  
  
    def test_default_severity(self):  
        logger = isc.log.Logger("child")  
        self.defaults(logger)  
  
    # Try changing the severities little bit  
    def test_severity(self):  
        logger = isc.log.Logger("child")  
        logger.set_severity('DEBUG', 25)  
        self.assertEqual(logger.get_effective_severity(), "DEBUG")  
        self.assertEqual(logger.get_effective_debug_level(), 25)  
        for sev in self.sevs:  
            logger.set_severity(sev)  
            self.assertEqual(logger.get_effective_severity(), sev)  
            self.assertEqual(logger.get_effective_debug_level(), 0)  
        # Return to default  
        logger.set_severity(None)  
        self.defaults(logger)  
  
    def test_enabled(self):  
        logger = isc.log.Logger("child")  
        self.sevs.insert(0, 'DEBUG')  
        methods = {  
            'DEBUG': logger.is_debug_enabled,  
            'INFO': logger.is_info_enabled,  
            'WARN': logger.is_warn_enabled,  
            'ERROR': logger.is_error_enabled,  
            'FATAL': logger.is_fatal_enabled  
        }  
        for sev in self.sevs:  
            logger.set_severity(sev)  
            enabled = False  
            for tested in self.sevs:  
                if tested == sev:  
                    enabled = True  
                self.assertEqual(methods[tested](), enabled)  
        logger.set_severity('DEBUG', 50)  
        self.assertTrue(logger.is_debug_enabled())  
        self.assertTrue(logger.is_debug_enabled(0))  
        self.assertTrue(logger.is_debug_enabled(50))  
        self.assertFalse(logger.is_debug_enabled(99))  
  
    def test_invalid_params(self):  
        """  
           Tests invalid arguments for logging functions. The output is tested  
           in check_output.sh.  
        """  
        logger = isc.log.Logger("child")  
        methods = [  
            logger.info,  
            logger.warn,  
            logger.error,  
            logger.fatal  
        ]  
        for meth in methods:  
            # Not enough arguments  
            self.assertRaises(TypeError, meth)  
            # Bad type  
            self.assertRaises(TypeError, meth, 1)  
        # Too few arguments  
        self.assertRaises(TypeError, logger.debug, 42)  
        self.assertRaises(TypeError, logger.debug)  
        # Bad type  
        self.assertRaises(TypeError, logger.debug, "42", "hello")  
  
    def test_dbglevel_constants(self):  
        """  
            Just check a constant to make sure it is defined and is the  
            correct value.  (The constant chosen has a non-zero value to  
            ensure that the code has both define the constant and set its  
            value correctly.)  
        """  
        logger = isc.log.Logger("child")  
        self.assertEqual(logger.DBGLVL_COMMAND, 10)  
  
    def test_param_reference(self):  
        """  
        Check whether passing a parameter to a logger causes a reference leak.  
        """  
        class LogParam:  
            def __str__(self):  
                return 'LogParam'  
        logger = isc.log.Logger("child")  
        param = LogParam()  
        orig_msgrefcnt = sys.getrefcount(param)  
        orig_idrefcnt = sys.getrefcount(self.TEST_MSG)  
        logger.info(self.TEST_MSG, param);  
        self.assertEqual(sys.getrefcount(self.TEST_MSG), orig_idrefcnt)  
        self.assertEqual(sys.getrefcount(param), orig_msgrefcnt)  
  
        # intentionally pass an invalid type for debug level.  It will  
        # result in TypeError.  The passed object still shouldn't leak a  
        # reference.  
        self.assertRaises(TypeError, logger.debug, param, self.TEST_MSG, param)  
        self.assertEqual(sys.getrefcount(param), orig_msgrefcnt)  
  
    def test_bad_parameter(self):  
        # a log parameter cannot be converted to a string object.  
        class LogParam:  
            def __str__(self):  
                raise ValueError("LogParam can't be converted to string")  
        logger = isc.log.Logger("child")  
        self.assertRaises(ValueError, logger.info, self.TEST_MSG, LogParam())  
  
exitif __name__ == '__main__':  
    unittest.main()  
                
             |