Logging config unit tests.
This commit is contained in:
parent
a4967b1338
commit
8f82420d7f
2 changed files with 95 additions and 9 deletions
|
@ -2,23 +2,19 @@
|
||||||
from typing import Any, Dict, Iterable, List, Tuple, Union
|
from typing import Any, Dict, Iterable, List, Tuple, Union
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import io
|
|
||||||
import sys
|
import sys
|
||||||
import logging
|
import logging
|
||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
|
|
||||||
|
|
||||||
def parse_logging(symbolic_level: str, symbolic_target: str) -> Tuple[int, logging.Handler]:
|
def parse_logging(symbolic_level: str, symbolic_target: str) -> Tuple[int, logging.Handler]:
|
||||||
level: int = logging.NOTSET
|
|
||||||
try:
|
try:
|
||||||
level = int(symbolic_level)
|
level: int = int(symbolic_level)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
try:
|
try:
|
||||||
level = int(logging.getLevelName(symbolic_level))
|
level = int(logging.getLevelName(symbolic_level))
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
raise ValueError(f'Unknown log level: {symbolic_level}')
|
||||||
if symbolic_target == 'stderr':
|
if symbolic_target == 'stderr':
|
||||||
target: logging.Handler = logging.StreamHandler(sys.stderr)
|
target: logging.Handler = logging.StreamHandler(sys.stderr)
|
||||||
elif symbolic_target == 'stdout':
|
elif symbolic_target == 'stdout':
|
||||||
|
@ -50,7 +46,7 @@ def parse_config_file(paths: Union[str, Iterable[str]]) -> Dict[str, Any]:
|
||||||
# Log level
|
# Log level
|
||||||
'log_level': logging.INFO,
|
'log_level': logging.INFO,
|
||||||
# Log target: An IO stream (stderr, stdout, ...) or a filename
|
# Log target: An IO stream (stderr, stdout, ...) or a filename
|
||||||
'log_handler': 'stderr',
|
'log_handler': logging.StreamHandler(),
|
||||||
# Variables passed to pagelets
|
# Variables passed to pagelets
|
||||||
'pagelet_variables': dict()
|
'pagelet_variables': dict()
|
||||||
}
|
}
|
||||||
|
@ -78,7 +74,7 @@ def parse_config_file(paths: Union[str, Iterable[str]]) -> Dict[str, Any]:
|
||||||
config['staticroot'] = parser['Matemat'].get('StaticPath', os.path.expanduser(config['staticroot']))
|
config['staticroot'] = parser['Matemat'].get('StaticPath', os.path.expanduser(config['staticroot']))
|
||||||
config['log_level'], config['log_handler'] =\
|
config['log_level'], config['log_handler'] =\
|
||||||
parse_logging(parser['Matemat'].get('LogLevel', config['log_level']),
|
parse_logging(parser['Matemat'].get('LogLevel', config['log_level']),
|
||||||
parser['Matemat'].get('LogTarget', config['log_handler']))
|
parser['Matemat'].get('LogTarget', 'stderr'))
|
||||||
config['templateroot'] = parser['Matemat'].get('TemplatePath', os.path.expanduser(config['templateroot']))
|
config['templateroot'] = parser['Matemat'].get('TemplatePath', os.path.expanduser(config['templateroot']))
|
||||||
|
|
||||||
# Read all values from the [Pagelets] section, if present. These values are passed to pagelet functions
|
# Read all values from the [Pagelets] section, if present. These values are passed to pagelet functions
|
||||||
|
|
|
@ -5,6 +5,8 @@ from unittest import TestCase
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
import logging
|
||||||
|
import sys
|
||||||
|
|
||||||
from matemat.webserver import parse_config_file
|
from matemat.webserver import parse_config_file
|
||||||
|
|
||||||
|
@ -19,6 +21,9 @@ Port = 8080
|
||||||
StaticPath =/var/test/static
|
StaticPath =/var/test/static
|
||||||
TemplatePath= /var/test/templates
|
TemplatePath= /var/test/templates
|
||||||
|
|
||||||
|
LogLevel = CRITICAL
|
||||||
|
LogTarget = /tmp/log/matemat_test.log
|
||||||
|
|
||||||
[Pagelets]
|
[Pagelets]
|
||||||
Name=Matemat
|
Name=Matemat
|
||||||
(Unit Test)
|
(Unit Test)
|
||||||
|
@ -34,6 +39,29 @@ Port=443
|
||||||
Name=Matemat (Unit Test 2)
|
Name=Matemat (Unit Test 2)
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
_LOG_NONE_CONFIG = '''
|
||||||
|
[Matemat]
|
||||||
|
LogTarget=none
|
||||||
|
'''
|
||||||
|
|
||||||
|
_LOG_STDOUT_CONFIG = '''
|
||||||
|
[Matemat]
|
||||||
|
LogTarget=stdout
|
||||||
|
'''
|
||||||
|
|
||||||
|
_LOG_STDERR_CONFIG = '''
|
||||||
|
[Matemat]
|
||||||
|
LogTarget=stderr
|
||||||
|
'''
|
||||||
|
|
||||||
|
_LOG_GARBAGE_PORT = '''
|
||||||
|
[Matemat]
|
||||||
|
Port=iwanttobeavalidporttoo'''
|
||||||
|
|
||||||
|
_LOG_GARBAGE_LOGLEVEL = '''
|
||||||
|
[Matemat]
|
||||||
|
LogLevel=thisisnotaloglevel'''
|
||||||
|
|
||||||
|
|
||||||
class IterOpenMock:
|
class IterOpenMock:
|
||||||
"""
|
"""
|
||||||
|
@ -59,7 +87,7 @@ class IterOpenMock:
|
||||||
|
|
||||||
class TestConfig(TestCase):
|
class TestConfig(TestCase):
|
||||||
|
|
||||||
def test_parse_config_empty_defualt_values(self):
|
def test_parse_config_empty_default_values(self):
|
||||||
"""
|
"""
|
||||||
Test that default values are set when reading an empty config file.
|
Test that default values are set when reading an empty config file.
|
||||||
"""
|
"""
|
||||||
|
@ -72,12 +100,17 @@ class TestConfig(TestCase):
|
||||||
self.assertIn('port', config)
|
self.assertIn('port', config)
|
||||||
self.assertIn('staticroot', config)
|
self.assertIn('staticroot', config)
|
||||||
self.assertIn('templateroot', config)
|
self.assertIn('templateroot', config)
|
||||||
|
self.assertIn('log_level', config)
|
||||||
|
self.assertIn('log_handler', config)
|
||||||
self.assertIn('pagelet_variables', config)
|
self.assertIn('pagelet_variables', config)
|
||||||
# Make sure all mandatory values are set to their default
|
# Make sure all mandatory values are set to their default
|
||||||
self.assertEqual('::', config['listen'])
|
self.assertEqual('::', config['listen'])
|
||||||
self.assertEqual(80, config['port'])
|
self.assertEqual(80, config['port'])
|
||||||
self.assertEqual('/var/matemat/static', config['staticroot'])
|
self.assertEqual('/var/matemat/static', config['staticroot'])
|
||||||
self.assertEqual('/var/matemat/templates', config['templateroot'])
|
self.assertEqual('/var/matemat/templates', config['templateroot'])
|
||||||
|
self.assertEqual(logging.INFO, config['log_level'])
|
||||||
|
self.assertIsInstance(config['log_handler'], logging.StreamHandler)
|
||||||
|
self.assertEqual(sys.stderr, config['log_handler'].stream)
|
||||||
self.assertIsInstance(config['pagelet_variables'], dict)
|
self.assertIsInstance(config['pagelet_variables'], dict)
|
||||||
self.assertEqual(0, len(config['pagelet_variables']))
|
self.assertEqual(0, len(config['pagelet_variables']))
|
||||||
|
|
||||||
|
@ -94,6 +127,8 @@ class TestConfig(TestCase):
|
||||||
self.assertIn('port', config)
|
self.assertIn('port', config)
|
||||||
self.assertIn('staticroot', config)
|
self.assertIn('staticroot', config)
|
||||||
self.assertIn('templateroot', config)
|
self.assertIn('templateroot', config)
|
||||||
|
self.assertIn('log_level', config)
|
||||||
|
self.assertIn('log_handler', config)
|
||||||
self.assertIn('pagelet_variables', config)
|
self.assertIn('pagelet_variables', config)
|
||||||
self.assertIn('Name', config['pagelet_variables'])
|
self.assertIn('Name', config['pagelet_variables'])
|
||||||
self.assertIn('UploadDir', config['pagelet_variables'])
|
self.assertIn('UploadDir', config['pagelet_variables'])
|
||||||
|
@ -103,6 +138,9 @@ class TestConfig(TestCase):
|
||||||
self.assertEqual(8080, config['port'])
|
self.assertEqual(8080, config['port'])
|
||||||
self.assertEqual('/var/test/static', config['staticroot'])
|
self.assertEqual('/var/test/static', config['staticroot'])
|
||||||
self.assertEqual('/var/test/templates', config['templateroot'])
|
self.assertEqual('/var/test/templates', config['templateroot'])
|
||||||
|
self.assertEqual(logging.CRITICAL, config['log_level'])
|
||||||
|
self.assertIsInstance(config['log_handler'], logging.FileHandler)
|
||||||
|
self.assertEqual('/tmp/log/matemat_test.log', config['log_handler'].baseFilename)
|
||||||
self.assertEqual('Matemat\n(Unit Test)', config['pagelet_variables']['Name'])
|
self.assertEqual('Matemat\n(Unit Test)', config['pagelet_variables']['Name'])
|
||||||
self.assertEqual('/var/test/static/upload', config['pagelet_variables']['UploadDir'])
|
self.assertEqual('/var/test/static/upload', config['pagelet_variables']['UploadDir'])
|
||||||
self.assertEqual('/var/test/db/test.db', config['pagelet_variables']['DatabaseFile'])
|
self.assertEqual('/var/test/db/test.db', config['pagelet_variables']['DatabaseFile'])
|
||||||
|
@ -134,3 +172,55 @@ class TestConfig(TestCase):
|
||||||
self.assertEqual('Matemat (Unit Test 2)', config['pagelet_variables']['Name'])
|
self.assertEqual('Matemat (Unit Test 2)', config['pagelet_variables']['Name'])
|
||||||
self.assertEqual('/var/test/static/upload', config['pagelet_variables']['UploadDir'])
|
self.assertEqual('/var/test/static/upload', config['pagelet_variables']['UploadDir'])
|
||||||
self.assertEqual('/var/test/db/test.db', config['pagelet_variables']['DatabaseFile'])
|
self.assertEqual('/var/test/db/test.db', config['pagelet_variables']['DatabaseFile'])
|
||||||
|
|
||||||
|
def test_parse_config_logging_none(self):
|
||||||
|
"""
|
||||||
|
Test that "LogTaget=none" disables logging.
|
||||||
|
"""
|
||||||
|
# Mock the open() function to return a config file example with disabled logging
|
||||||
|
with patch('builtins.open', return_value=StringIO(_LOG_NONE_CONFIG)):
|
||||||
|
# The filename is only a placeholder, file content is determined by mocking open
|
||||||
|
config = parse_config_file('test')
|
||||||
|
# Make sure the returned log handler is a null handler
|
||||||
|
self.assertIsInstance(config['log_handler'], logging.NullHandler)
|
||||||
|
|
||||||
|
def test_parse_config_logging_stdout(self):
|
||||||
|
"""
|
||||||
|
Test that "LogTaget=stdout" logs to sys.stdout.
|
||||||
|
"""
|
||||||
|
# Mock the open() function to return a config file example with stdout logging
|
||||||
|
with patch('builtins.open', return_value=StringIO(_LOG_STDOUT_CONFIG)):
|
||||||
|
# The filename is only a placeholder, file content is determined by mocking open
|
||||||
|
config = parse_config_file('test')
|
||||||
|
# Make sure the returned log handler is a stdout handler
|
||||||
|
self.assertIsInstance(config['log_handler'], logging.StreamHandler)
|
||||||
|
self.assertEqual(sys.stdout, config['log_handler'].stream)
|
||||||
|
|
||||||
|
def test_parse_config_logging_stderr(self):
|
||||||
|
"""
|
||||||
|
Test that "LogTaget=stderr" logs to sys.stderr.
|
||||||
|
"""
|
||||||
|
# Mock the open() function to return a config file example with stdout logging
|
||||||
|
with patch('builtins.open', return_value=StringIO(_LOG_STDERR_CONFIG)):
|
||||||
|
# The filename is only a placeholder, file content is determined by mocking open
|
||||||
|
config = parse_config_file('test')
|
||||||
|
# Make sure the returned log handler is a stdout handler
|
||||||
|
self.assertIsInstance(config['log_handler'], logging.StreamHandler)
|
||||||
|
self.assertEqual(sys.stderr, config['log_handler'].stream)
|
||||||
|
|
||||||
|
def test_parse_config_garbage(self):
|
||||||
|
"""
|
||||||
|
Test that garbage config raises ValueErrors.
|
||||||
|
"""
|
||||||
|
# Mock the open() function to return a config file example with a non-numeric port
|
||||||
|
with patch('builtins.open', return_value=StringIO(_LOG_GARBAGE_PORT)):
|
||||||
|
# Make sure a ValueError is raised
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
# The filename is only a placeholder, file content is determined by mocking open
|
||||||
|
parse_config_file('test')
|
||||||
|
# Mock the open() function to return a config file example with a non-numeric log level with invalid symbol
|
||||||
|
with patch('builtins.open', return_value=StringIO(_LOG_GARBAGE_LOGLEVEL)):
|
||||||
|
# Make sure a ValueError is raised
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
# The filename is only a placeholder, file content is determined by mocking open
|
||||||
|
parse_config_file('test')
|
||||||
|
|
Loading…
Reference in a new issue