Clean up, remove compat with py < 3.6
[pyi2ncommon] / test / test_log_helpers.py
CommitLineData
c71df627
CH
1#!/usr/bin/env python3
2
3"""
4Test log_helpers.
5
6.. codeauthor:: Intra2net AG <info@intra2net.com>
7"""
8
c71df627
CH
9import unittest
10import logging
11from tempfile import mkstemp
12import os
13from os.path import isfile, basename
14import re
15
16from src import log_helpers
17
18
19class LogHelperTest(unittest.TestCase):
20
21 def setUp(self):
22 """Create temp file to write log to."""
23 descriptor, self.temp_name = mkstemp(
24 prefix='pyi2ncommon-test-log-helpers-', suffix='.log', text=True)
25 self.temp_handle = os.fdopen(descriptor, 'at')
26
27 def tearDown(self):
28 """Remove temp log file."""
29 self.temp_handle.close()
30 if isfile(self.temp_name):
31 os.unlink(self.temp_name)
32
33 def get_logger_name(self):
34 """Return a unique name for a logger."""
35 return 'logtest-' + basename(self.temp_name)
36
37 def check_expected_contents(self, expected_contents):
38 """
39 Helper for other tests: open temp file, compare contents.
40
41 Ignores timestamp and line numbers
42 """
43 self.temp_handle.close()
44 with open(self.temp_name, 'rt') as log_reader:
45 for line_no, (actual_line, expect_line) in \
46 enumerate(zip(log_reader, expected_contents.splitlines())):
47 if re.match(r'\d{1,2}:\d{2}:\d{2}:\d{3}\s+', actual_line):
48 cmp_line = actual_line[13:].rstrip()
49 elif re.match(r'\s*File ".+", line \d+, in .+', actual_line):
50 cmp_line = ' TRACEBACK LINE REPLACED'
51 else:
52 cmp_line = actual_line.rstrip()
53 self.assertEqual(cmp_line, expect_line)
54
55 def test_short_level_format(self):
56 """Tests that calls to :py:class:`ShortLevelFormatter` do not fail."""
57 logger = logging.getLogger(self.get_logger_name())
58 logger.setLevel(logging.DEBUG)
59 handler = logging.StreamHandler(self.temp_handle)
60 handler.setLevel(logging.DEBUG)
61 formatter = log_helpers.ShortLevelFormatter(
62 '%(asctime)s:%(msecs)03d %(shortlevel)s| %(msg)s'
63 ' [regular levelname=%(levelname)s]',
64 datefmt='%H:%M:%S')
65 handler.setFormatter(formatter)
66 logger.addHandler(handler)
67
68 # 'application' code
69 logger.debug('debug message')
70 logger.info('info message')
71 logger.warning('warn message')
72 logger.error('error message')
73 logger.critical('critical message')
74 logger.log(15, 'unknown level')
75 logger.log(logging.NOTSET, 'level not set')
76
77 # add notice level
78 notice = (logging.INFO + logging.WARNING)//2
79 formatter.add_level(notice, 'note')
80 logger.log(notice, 'more important than info but no warning nor error')
81
82 # try if exception formatting still works:
83 try:
84 logger.info('this is what an exception looks like:')
85 impossible_result = 1/0
86 logger.critical('just divided 1/0! The result is {0}'
87 .format(impossible_result))
88 except ZeroDivisionError:
89 logger.exception('1/0 still does not work!', exc_info=True)
90
91 # done
92 logger.info('done testing')
93
94 # now check the file
95 expected_contents = \
96 'dbug| debug message [regular levelname=DEBUG]\n' \
97 'info| info message [regular levelname=INFO]\n' \
98 'warn| warn message [regular levelname=WARNING]\n' \
99 'err | error message [regular levelname=ERROR]\n' \
100 'crit| critical message [regular levelname=CRITICAL]\n' \
101 '????| unknown level [regular levelname=Level 15]\n' \
102 'note| more important than info but no warning nor error [regular levelname=NOTICE]\n' \
103 'info| this is what an exception looks like: [regular levelname=INFO]\n' \
104 'err | 1/0 still does not work! [regular levelname=ERROR]\n' \
105 'Traceback (most recent call last):\n' \
106 ' TRACEBACK LINE REPLACED\n' \
107 ' impossible_result = 1/0\n' \
108 'ZeroDivisionError: division by zero\n' \
109 'info| done testing [regular levelname=INFO]\n'
110 self.check_expected_contents(expected_contents)
111
112 def test_get_logger(self):
113 log = log_helpers.get_logger('logger_test')
114 log2 = log_helpers.get_logger('logger_test')
115 self.assertEqual(log, log2)
116
117 def test_interesting_lines(self):
118 log = log_helpers.get_logger(self.get_logger_name(),
119 streams=self.temp_handle)
120 for idx in range(20):
121 log.log_count_if_interesting(idx)
122
123 expected_contents = 'info| Counter is at 1\n' \
124 'info| Counter is at 2\n' \
125 'info| Counter is at 3\n' \
126 'info| Counter is at 6\n' \
127 'info| Counter is at 10\n'
128 self.check_expected_contents(expected_contents)
129
130 def test_error_in_formatting(self):
131 """Ensure that forgotten args to not raise err but issue warning."""
132 self.check_expected_contents(expected_contents)
133
134 def test_error_in_formatting(self):
135 """Ensure that forgotten args to not raise err but issue warning."""
136 log = log_helpers.get_logger(self.get_logger_name(),
137 streams=self.temp_handle)
138 log.warn('forgot to add argument {} and {1} and {cnf} to format string')
139 log.warn('wrong number {} of arguments {}', 1)
140
141 expected_contents = \
142 'warn| [LOG ARGS!] forgot to add argument {} and {1} and {cnf} ' \
143 'to format string\n' \
144 'warn| [LOG ARGS!] wrong number {} of arguments {}\n'
145 self.check_expected_contents(expected_contents)
146
147
148if __name__ == '__main__':
149 unittest.main()