1"""
2    :codeauthor: Pedro Algarvio (pedro@algarvio.me)
3
4
5    tests.unit.log_test
6    ~~~~~~~~~~~~~~~~~~~
7
8    Test salt's "hacked" logging
9"""
10
11
12import io
13import logging
14
15from salt._logging.handlers import StreamHandler
16from salt._logging.impl import SaltLoggingClass
17from tests.support.case import TestCase
18from tests.support.helpers import TstSuiteLoggingHandler
19
20
21class TestLog(TestCase):
22    """
23    Test several logging settings
24    """
25
26    def test_issue_2853_regex_TypeError(self):
27        # Now, python's logging logger class is ours.
28        # Let's make sure we have at least one instance
29        log = SaltLoggingClass(__name__)
30
31        # Test for a format which includes digits in name formatting.
32        log_format = "[%(name)-15s] %(message)s"
33        handler = TstSuiteLoggingHandler(format=log_format)
34        log.addHandler(handler)
35
36        # Trigger TstSuiteLoggingHandler.__enter__
37        with handler:
38            # Let's create another log instance to trigger salt's logging class
39            # calculations.
40            try:
41                SaltLoggingClass("{}.with_digits".format(__name__))
42            except Exception as err:  # pylint: disable=broad-except
43                raise AssertionError(
44                    "No exception should have been raised: {}".format(err)
45                )
46
47        # Remove the testing handler
48        log.removeHandler(handler)
49
50        # Test for a format which does not include digits in name formatting.
51        log_format = "[%(name)s] %(message)s"
52        handler = TstSuiteLoggingHandler(format=log_format)
53        log.addHandler(handler)
54
55        # Trigger TstSuiteLoggingHandler.__enter__
56        with handler:
57            # Let's create another log instance to trigger salt's logging class
58            # calculations.
59            try:
60                SaltLoggingClass("{}.without_digits".format(__name__))
61            except Exception as err:  # pylint: disable=broad-except
62                raise AssertionError(
63                    "No exception should have been raised: {}".format(err)
64                )
65
66            # Remove the testing handler
67            log.removeHandler(handler)
68
69    def test_exc_info_on_loglevel(self):
70        def raise_exception_on_purpose():
71            1 / 0  # pylint: disable=pointless-statement
72
73        log = SaltLoggingClass(__name__)
74
75        # Only stream2 should contain the traceback
76        stream1 = io.StringIO()
77        stream2 = io.StringIO()
78        handler1 = StreamHandler(stream1)
79        handler2 = StreamHandler(stream2)
80
81        handler1.setLevel(logging.INFO)
82        handler2.setLevel(logging.DEBUG)
83
84        log.addHandler(handler1)
85        log.addHandler(handler2)
86
87        try:
88            raise_exception_on_purpose()
89        except ZeroDivisionError as exc:
90            log.error(
91                "Exception raised on purpose caught: ZeroDivisionError",
92                exc_info_on_loglevel=logging.DEBUG,
93            )
94
95        try:
96            self.assertIn(
97                "Exception raised on purpose caught: ZeroDivisionError",
98                stream1.getvalue(),
99            )
100            self.assertNotIn("Traceback (most recent call last)", stream1.getvalue())
101            self.assertIn(
102                "Exception raised on purpose caught: ZeroDivisionError",
103                stream2.getvalue(),
104            )
105            self.assertIn("Traceback (most recent call last)", stream2.getvalue())
106        finally:
107            log.removeHandler(handler1)
108            log.removeHandler(handler2)
109
110        # Both streams should contain the traceback
111        stream1 = io.StringIO()
112        stream2 = io.StringIO()
113        handler1 = StreamHandler(stream1)
114        handler2 = StreamHandler(stream2)
115
116        handler1.setLevel(logging.INFO)
117        handler2.setLevel(logging.DEBUG)
118
119        log.addHandler(handler1)
120        log.addHandler(handler2)
121
122        try:
123            raise_exception_on_purpose()
124        except ZeroDivisionError as exc:
125            log.error(
126                "Exception raised on purpose caught: ZeroDivisionError",
127                exc_info_on_loglevel=logging.INFO,
128            )
129
130        try:
131            self.assertIn(
132                "Exception raised on purpose caught: ZeroDivisionError",
133                stream1.getvalue(),
134            )
135            self.assertIn("Traceback (most recent call last)", stream1.getvalue())
136            self.assertIn(
137                "Exception raised on purpose caught: ZeroDivisionError",
138                stream2.getvalue(),
139            )
140            self.assertIn("Traceback (most recent call last)", stream2.getvalue())
141        finally:
142            log.removeHandler(handler1)
143            log.removeHandler(handler2)
144
145        # No streams should contain the traceback
146        stream1 = io.StringIO()
147        stream2 = io.StringIO()
148        handler1 = StreamHandler(stream1)
149        handler2 = StreamHandler(stream2)
150
151        handler1.setLevel(logging.ERROR)
152        handler2.setLevel(logging.INFO)
153
154        log.addHandler(handler1)
155        log.addHandler(handler2)
156
157        try:
158            raise_exception_on_purpose()
159        except ZeroDivisionError as exc:
160            log.error(
161                "Exception raised on purpose caught: ZeroDivisionError",
162                exc_info_on_loglevel=logging.DEBUG,
163            )
164
165        try:
166            self.assertIn(
167                "Exception raised on purpose caught: ZeroDivisionError",
168                stream1.getvalue(),
169            )
170            self.assertNotIn("Traceback (most recent call last)", stream1.getvalue())
171            self.assertIn(
172                "Exception raised on purpose caught: ZeroDivisionError",
173                stream2.getvalue(),
174            )
175            self.assertNotIn("Traceback (most recent call last)", stream2.getvalue())
176        finally:
177            log.removeHandler(handler1)
178            log.removeHandler(handler2)
179