17db96d56Sopenharmony_ci# Copyright 2001-2022 by Vinay Sajip. All Rights Reserved.
27db96d56Sopenharmony_ci#
37db96d56Sopenharmony_ci# Permission to use, copy, modify, and distribute this software and its
47db96d56Sopenharmony_ci# documentation for any purpose and without fee is hereby granted,
57db96d56Sopenharmony_ci# provided that the above copyright notice appear in all copies and that
67db96d56Sopenharmony_ci# both that copyright notice and this permission notice appear in
77db96d56Sopenharmony_ci# supporting documentation, and that the name of Vinay Sajip
87db96d56Sopenharmony_ci# not be used in advertising or publicity pertaining to distribution
97db96d56Sopenharmony_ci# of the software without specific, written prior permission.
107db96d56Sopenharmony_ci# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
117db96d56Sopenharmony_ci# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
127db96d56Sopenharmony_ci# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
137db96d56Sopenharmony_ci# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
147db96d56Sopenharmony_ci# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
157db96d56Sopenharmony_ci# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
167db96d56Sopenharmony_ci
177db96d56Sopenharmony_ci"""Test harness for the logging module. Run all tests.
187db96d56Sopenharmony_ci
197db96d56Sopenharmony_ciCopyright (C) 2001-2022 Vinay Sajip. All Rights Reserved.
207db96d56Sopenharmony_ci"""
217db96d56Sopenharmony_ci
227db96d56Sopenharmony_ciimport logging
237db96d56Sopenharmony_ciimport logging.handlers
247db96d56Sopenharmony_ciimport logging.config
257db96d56Sopenharmony_ci
267db96d56Sopenharmony_ciimport codecs
277db96d56Sopenharmony_ciimport configparser
287db96d56Sopenharmony_ciimport copy
297db96d56Sopenharmony_ciimport datetime
307db96d56Sopenharmony_ciimport pathlib
317db96d56Sopenharmony_ciimport pickle
327db96d56Sopenharmony_ciimport io
337db96d56Sopenharmony_ciimport gc
347db96d56Sopenharmony_ciimport json
357db96d56Sopenharmony_ciimport os
367db96d56Sopenharmony_ciimport queue
377db96d56Sopenharmony_ciimport random
387db96d56Sopenharmony_ciimport re
397db96d56Sopenharmony_ciimport shutil
407db96d56Sopenharmony_ciimport socket
417db96d56Sopenharmony_ciimport struct
427db96d56Sopenharmony_ciimport sys
437db96d56Sopenharmony_ciimport tempfile
447db96d56Sopenharmony_cifrom test.support.script_helper import assert_python_ok, assert_python_failure
457db96d56Sopenharmony_cifrom test import support
467db96d56Sopenharmony_cifrom test.support import os_helper
477db96d56Sopenharmony_cifrom test.support import socket_helper
487db96d56Sopenharmony_cifrom test.support import threading_helper
497db96d56Sopenharmony_cifrom test.support import warnings_helper
507db96d56Sopenharmony_cifrom test.support.logging_helper import TestHandler
517db96d56Sopenharmony_ciimport textwrap
527db96d56Sopenharmony_ciimport threading
537db96d56Sopenharmony_ciimport time
547db96d56Sopenharmony_ciimport unittest
557db96d56Sopenharmony_ciimport warnings
567db96d56Sopenharmony_ciimport weakref
577db96d56Sopenharmony_ci
587db96d56Sopenharmony_cifrom http.server import HTTPServer, BaseHTTPRequestHandler
597db96d56Sopenharmony_cifrom urllib.parse import urlparse, parse_qs
607db96d56Sopenharmony_cifrom socketserver import (ThreadingUDPServer, DatagramRequestHandler,
617db96d56Sopenharmony_ci                          ThreadingTCPServer, StreamRequestHandler)
627db96d56Sopenharmony_ci
637db96d56Sopenharmony_ci
647db96d56Sopenharmony_ciasyncore = warnings_helper.import_deprecated('asyncore')
657db96d56Sopenharmony_cismtpd = warnings_helper.import_deprecated('smtpd')
667db96d56Sopenharmony_ci
677db96d56Sopenharmony_ci
687db96d56Sopenharmony_citry:
697db96d56Sopenharmony_ci    import win32evtlog, win32evtlogutil, pywintypes
707db96d56Sopenharmony_ciexcept ImportError:
717db96d56Sopenharmony_ci    win32evtlog = win32evtlogutil = pywintypes = None
727db96d56Sopenharmony_ci
737db96d56Sopenharmony_citry:
747db96d56Sopenharmony_ci    import zlib
757db96d56Sopenharmony_ciexcept ImportError:
767db96d56Sopenharmony_ci    pass
777db96d56Sopenharmony_ci
787db96d56Sopenharmony_ci
797db96d56Sopenharmony_ciclass BaseTest(unittest.TestCase):
807db96d56Sopenharmony_ci
817db96d56Sopenharmony_ci    """Base class for logging tests."""
827db96d56Sopenharmony_ci
837db96d56Sopenharmony_ci    log_format = "%(name)s -> %(levelname)s: %(message)s"
847db96d56Sopenharmony_ci    expected_log_pat = r"^([\w.]+) -> (\w+): (\d+)$"
857db96d56Sopenharmony_ci    message_num = 0
867db96d56Sopenharmony_ci
877db96d56Sopenharmony_ci    def setUp(self):
887db96d56Sopenharmony_ci        """Setup the default logging stream to an internal StringIO instance,
897db96d56Sopenharmony_ci        so that we can examine log output as we want."""
907db96d56Sopenharmony_ci        self._threading_key = threading_helper.threading_setup()
917db96d56Sopenharmony_ci
927db96d56Sopenharmony_ci        logger_dict = logging.getLogger().manager.loggerDict
937db96d56Sopenharmony_ci        logging._acquireLock()
947db96d56Sopenharmony_ci        try:
957db96d56Sopenharmony_ci            self.saved_handlers = logging._handlers.copy()
967db96d56Sopenharmony_ci            self.saved_handler_list = logging._handlerList[:]
977db96d56Sopenharmony_ci            self.saved_loggers = saved_loggers = logger_dict.copy()
987db96d56Sopenharmony_ci            self.saved_name_to_level = logging._nameToLevel.copy()
997db96d56Sopenharmony_ci            self.saved_level_to_name = logging._levelToName.copy()
1007db96d56Sopenharmony_ci            self.logger_states = logger_states = {}
1017db96d56Sopenharmony_ci            for name in saved_loggers:
1027db96d56Sopenharmony_ci                logger_states[name] = getattr(saved_loggers[name],
1037db96d56Sopenharmony_ci                                              'disabled', None)
1047db96d56Sopenharmony_ci        finally:
1057db96d56Sopenharmony_ci            logging._releaseLock()
1067db96d56Sopenharmony_ci
1077db96d56Sopenharmony_ci        # Set two unused loggers
1087db96d56Sopenharmony_ci        self.logger1 = logging.getLogger("\xab\xd7\xbb")
1097db96d56Sopenharmony_ci        self.logger2 = logging.getLogger("\u013f\u00d6\u0047")
1107db96d56Sopenharmony_ci
1117db96d56Sopenharmony_ci        self.root_logger = logging.getLogger("")
1127db96d56Sopenharmony_ci        self.original_logging_level = self.root_logger.getEffectiveLevel()
1137db96d56Sopenharmony_ci
1147db96d56Sopenharmony_ci        self.stream = io.StringIO()
1157db96d56Sopenharmony_ci        self.root_logger.setLevel(logging.DEBUG)
1167db96d56Sopenharmony_ci        self.root_hdlr = logging.StreamHandler(self.stream)
1177db96d56Sopenharmony_ci        self.root_formatter = logging.Formatter(self.log_format)
1187db96d56Sopenharmony_ci        self.root_hdlr.setFormatter(self.root_formatter)
1197db96d56Sopenharmony_ci        if self.logger1.hasHandlers():
1207db96d56Sopenharmony_ci            hlist = self.logger1.handlers + self.root_logger.handlers
1217db96d56Sopenharmony_ci            raise AssertionError('Unexpected handlers: %s' % hlist)
1227db96d56Sopenharmony_ci        if self.logger2.hasHandlers():
1237db96d56Sopenharmony_ci            hlist = self.logger2.handlers + self.root_logger.handlers
1247db96d56Sopenharmony_ci            raise AssertionError('Unexpected handlers: %s' % hlist)
1257db96d56Sopenharmony_ci        self.root_logger.addHandler(self.root_hdlr)
1267db96d56Sopenharmony_ci        self.assertTrue(self.logger1.hasHandlers())
1277db96d56Sopenharmony_ci        self.assertTrue(self.logger2.hasHandlers())
1287db96d56Sopenharmony_ci
1297db96d56Sopenharmony_ci    def tearDown(self):
1307db96d56Sopenharmony_ci        """Remove our logging stream, and restore the original logging
1317db96d56Sopenharmony_ci        level."""
1327db96d56Sopenharmony_ci        self.stream.close()
1337db96d56Sopenharmony_ci        self.root_logger.removeHandler(self.root_hdlr)
1347db96d56Sopenharmony_ci        while self.root_logger.handlers:
1357db96d56Sopenharmony_ci            h = self.root_logger.handlers[0]
1367db96d56Sopenharmony_ci            self.root_logger.removeHandler(h)
1377db96d56Sopenharmony_ci            h.close()
1387db96d56Sopenharmony_ci        self.root_logger.setLevel(self.original_logging_level)
1397db96d56Sopenharmony_ci        logging._acquireLock()
1407db96d56Sopenharmony_ci        try:
1417db96d56Sopenharmony_ci            logging._levelToName.clear()
1427db96d56Sopenharmony_ci            logging._levelToName.update(self.saved_level_to_name)
1437db96d56Sopenharmony_ci            logging._nameToLevel.clear()
1447db96d56Sopenharmony_ci            logging._nameToLevel.update(self.saved_name_to_level)
1457db96d56Sopenharmony_ci            logging._handlers.clear()
1467db96d56Sopenharmony_ci            logging._handlers.update(self.saved_handlers)
1477db96d56Sopenharmony_ci            logging._handlerList[:] = self.saved_handler_list
1487db96d56Sopenharmony_ci            manager = logging.getLogger().manager
1497db96d56Sopenharmony_ci            manager.disable = 0
1507db96d56Sopenharmony_ci            loggerDict = manager.loggerDict
1517db96d56Sopenharmony_ci            loggerDict.clear()
1527db96d56Sopenharmony_ci            loggerDict.update(self.saved_loggers)
1537db96d56Sopenharmony_ci            logger_states = self.logger_states
1547db96d56Sopenharmony_ci            for name in self.logger_states:
1557db96d56Sopenharmony_ci                if logger_states[name] is not None:
1567db96d56Sopenharmony_ci                    self.saved_loggers[name].disabled = logger_states[name]
1577db96d56Sopenharmony_ci        finally:
1587db96d56Sopenharmony_ci            logging._releaseLock()
1597db96d56Sopenharmony_ci
1607db96d56Sopenharmony_ci        self.doCleanups()
1617db96d56Sopenharmony_ci        threading_helper.threading_cleanup(*self._threading_key)
1627db96d56Sopenharmony_ci
1637db96d56Sopenharmony_ci    def assert_log_lines(self, expected_values, stream=None, pat=None):
1647db96d56Sopenharmony_ci        """Match the collected log lines against the regular expression
1657db96d56Sopenharmony_ci        self.expected_log_pat, and compare the extracted group values to
1667db96d56Sopenharmony_ci        the expected_values list of tuples."""
1677db96d56Sopenharmony_ci        stream = stream or self.stream
1687db96d56Sopenharmony_ci        pat = re.compile(pat or self.expected_log_pat)
1697db96d56Sopenharmony_ci        actual_lines = stream.getvalue().splitlines()
1707db96d56Sopenharmony_ci        self.assertEqual(len(actual_lines), len(expected_values))
1717db96d56Sopenharmony_ci        for actual, expected in zip(actual_lines, expected_values):
1727db96d56Sopenharmony_ci            match = pat.search(actual)
1737db96d56Sopenharmony_ci            if not match:
1747db96d56Sopenharmony_ci                self.fail("Log line does not match expected pattern:\n" +
1757db96d56Sopenharmony_ci                            actual)
1767db96d56Sopenharmony_ci            self.assertEqual(tuple(match.groups()), expected)
1777db96d56Sopenharmony_ci        s = stream.read()
1787db96d56Sopenharmony_ci        if s:
1797db96d56Sopenharmony_ci            self.fail("Remaining output at end of log stream:\n" + s)
1807db96d56Sopenharmony_ci
1817db96d56Sopenharmony_ci    def next_message(self):
1827db96d56Sopenharmony_ci        """Generate a message consisting solely of an auto-incrementing
1837db96d56Sopenharmony_ci        integer."""
1847db96d56Sopenharmony_ci        self.message_num += 1
1857db96d56Sopenharmony_ci        return "%d" % self.message_num
1867db96d56Sopenharmony_ci
1877db96d56Sopenharmony_ci
1887db96d56Sopenharmony_ciclass BuiltinLevelsTest(BaseTest):
1897db96d56Sopenharmony_ci    """Test builtin levels and their inheritance."""
1907db96d56Sopenharmony_ci
1917db96d56Sopenharmony_ci    def test_flat(self):
1927db96d56Sopenharmony_ci        # Logging levels in a flat logger namespace.
1937db96d56Sopenharmony_ci        m = self.next_message
1947db96d56Sopenharmony_ci
1957db96d56Sopenharmony_ci        ERR = logging.getLogger("ERR")
1967db96d56Sopenharmony_ci        ERR.setLevel(logging.ERROR)
1977db96d56Sopenharmony_ci        INF = logging.LoggerAdapter(logging.getLogger("INF"), {})
1987db96d56Sopenharmony_ci        INF.setLevel(logging.INFO)
1997db96d56Sopenharmony_ci        DEB = logging.getLogger("DEB")
2007db96d56Sopenharmony_ci        DEB.setLevel(logging.DEBUG)
2017db96d56Sopenharmony_ci
2027db96d56Sopenharmony_ci        # These should log.
2037db96d56Sopenharmony_ci        ERR.log(logging.CRITICAL, m())
2047db96d56Sopenharmony_ci        ERR.error(m())
2057db96d56Sopenharmony_ci
2067db96d56Sopenharmony_ci        INF.log(logging.CRITICAL, m())
2077db96d56Sopenharmony_ci        INF.error(m())
2087db96d56Sopenharmony_ci        INF.warning(m())
2097db96d56Sopenharmony_ci        INF.info(m())
2107db96d56Sopenharmony_ci
2117db96d56Sopenharmony_ci        DEB.log(logging.CRITICAL, m())
2127db96d56Sopenharmony_ci        DEB.error(m())
2137db96d56Sopenharmony_ci        DEB.warning(m())
2147db96d56Sopenharmony_ci        DEB.info(m())
2157db96d56Sopenharmony_ci        DEB.debug(m())
2167db96d56Sopenharmony_ci
2177db96d56Sopenharmony_ci        # These should not log.
2187db96d56Sopenharmony_ci        ERR.warning(m())
2197db96d56Sopenharmony_ci        ERR.info(m())
2207db96d56Sopenharmony_ci        ERR.debug(m())
2217db96d56Sopenharmony_ci
2227db96d56Sopenharmony_ci        INF.debug(m())
2237db96d56Sopenharmony_ci
2247db96d56Sopenharmony_ci        self.assert_log_lines([
2257db96d56Sopenharmony_ci            ('ERR', 'CRITICAL', '1'),
2267db96d56Sopenharmony_ci            ('ERR', 'ERROR', '2'),
2277db96d56Sopenharmony_ci            ('INF', 'CRITICAL', '3'),
2287db96d56Sopenharmony_ci            ('INF', 'ERROR', '4'),
2297db96d56Sopenharmony_ci            ('INF', 'WARNING', '5'),
2307db96d56Sopenharmony_ci            ('INF', 'INFO', '6'),
2317db96d56Sopenharmony_ci            ('DEB', 'CRITICAL', '7'),
2327db96d56Sopenharmony_ci            ('DEB', 'ERROR', '8'),
2337db96d56Sopenharmony_ci            ('DEB', 'WARNING', '9'),
2347db96d56Sopenharmony_ci            ('DEB', 'INFO', '10'),
2357db96d56Sopenharmony_ci            ('DEB', 'DEBUG', '11'),
2367db96d56Sopenharmony_ci        ])
2377db96d56Sopenharmony_ci
2387db96d56Sopenharmony_ci    def test_nested_explicit(self):
2397db96d56Sopenharmony_ci        # Logging levels in a nested namespace, all explicitly set.
2407db96d56Sopenharmony_ci        m = self.next_message
2417db96d56Sopenharmony_ci
2427db96d56Sopenharmony_ci        INF = logging.getLogger("INF")
2437db96d56Sopenharmony_ci        INF.setLevel(logging.INFO)
2447db96d56Sopenharmony_ci        INF_ERR  = logging.getLogger("INF.ERR")
2457db96d56Sopenharmony_ci        INF_ERR.setLevel(logging.ERROR)
2467db96d56Sopenharmony_ci
2477db96d56Sopenharmony_ci        # These should log.
2487db96d56Sopenharmony_ci        INF_ERR.log(logging.CRITICAL, m())
2497db96d56Sopenharmony_ci        INF_ERR.error(m())
2507db96d56Sopenharmony_ci
2517db96d56Sopenharmony_ci        # These should not log.
2527db96d56Sopenharmony_ci        INF_ERR.warning(m())
2537db96d56Sopenharmony_ci        INF_ERR.info(m())
2547db96d56Sopenharmony_ci        INF_ERR.debug(m())
2557db96d56Sopenharmony_ci
2567db96d56Sopenharmony_ci        self.assert_log_lines([
2577db96d56Sopenharmony_ci            ('INF.ERR', 'CRITICAL', '1'),
2587db96d56Sopenharmony_ci            ('INF.ERR', 'ERROR', '2'),
2597db96d56Sopenharmony_ci        ])
2607db96d56Sopenharmony_ci
2617db96d56Sopenharmony_ci    def test_nested_inherited(self):
2627db96d56Sopenharmony_ci        # Logging levels in a nested namespace, inherited from parent loggers.
2637db96d56Sopenharmony_ci        m = self.next_message
2647db96d56Sopenharmony_ci
2657db96d56Sopenharmony_ci        INF = logging.getLogger("INF")
2667db96d56Sopenharmony_ci        INF.setLevel(logging.INFO)
2677db96d56Sopenharmony_ci        INF_ERR  = logging.getLogger("INF.ERR")
2687db96d56Sopenharmony_ci        INF_ERR.setLevel(logging.ERROR)
2697db96d56Sopenharmony_ci        INF_UNDEF = logging.getLogger("INF.UNDEF")
2707db96d56Sopenharmony_ci        INF_ERR_UNDEF = logging.getLogger("INF.ERR.UNDEF")
2717db96d56Sopenharmony_ci        UNDEF = logging.getLogger("UNDEF")
2727db96d56Sopenharmony_ci
2737db96d56Sopenharmony_ci        # These should log.
2747db96d56Sopenharmony_ci        INF_UNDEF.log(logging.CRITICAL, m())
2757db96d56Sopenharmony_ci        INF_UNDEF.error(m())
2767db96d56Sopenharmony_ci        INF_UNDEF.warning(m())
2777db96d56Sopenharmony_ci        INF_UNDEF.info(m())
2787db96d56Sopenharmony_ci        INF_ERR_UNDEF.log(logging.CRITICAL, m())
2797db96d56Sopenharmony_ci        INF_ERR_UNDEF.error(m())
2807db96d56Sopenharmony_ci
2817db96d56Sopenharmony_ci        # These should not log.
2827db96d56Sopenharmony_ci        INF_UNDEF.debug(m())
2837db96d56Sopenharmony_ci        INF_ERR_UNDEF.warning(m())
2847db96d56Sopenharmony_ci        INF_ERR_UNDEF.info(m())
2857db96d56Sopenharmony_ci        INF_ERR_UNDEF.debug(m())
2867db96d56Sopenharmony_ci
2877db96d56Sopenharmony_ci        self.assert_log_lines([
2887db96d56Sopenharmony_ci            ('INF.UNDEF', 'CRITICAL', '1'),
2897db96d56Sopenharmony_ci            ('INF.UNDEF', 'ERROR', '2'),
2907db96d56Sopenharmony_ci            ('INF.UNDEF', 'WARNING', '3'),
2917db96d56Sopenharmony_ci            ('INF.UNDEF', 'INFO', '4'),
2927db96d56Sopenharmony_ci            ('INF.ERR.UNDEF', 'CRITICAL', '5'),
2937db96d56Sopenharmony_ci            ('INF.ERR.UNDEF', 'ERROR', '6'),
2947db96d56Sopenharmony_ci        ])
2957db96d56Sopenharmony_ci
2967db96d56Sopenharmony_ci    def test_nested_with_virtual_parent(self):
2977db96d56Sopenharmony_ci        # Logging levels when some parent does not exist yet.
2987db96d56Sopenharmony_ci        m = self.next_message
2997db96d56Sopenharmony_ci
3007db96d56Sopenharmony_ci        INF = logging.getLogger("INF")
3017db96d56Sopenharmony_ci        GRANDCHILD = logging.getLogger("INF.BADPARENT.UNDEF")
3027db96d56Sopenharmony_ci        CHILD = logging.getLogger("INF.BADPARENT")
3037db96d56Sopenharmony_ci        INF.setLevel(logging.INFO)
3047db96d56Sopenharmony_ci
3057db96d56Sopenharmony_ci        # These should log.
3067db96d56Sopenharmony_ci        GRANDCHILD.log(logging.FATAL, m())
3077db96d56Sopenharmony_ci        GRANDCHILD.info(m())
3087db96d56Sopenharmony_ci        CHILD.log(logging.FATAL, m())
3097db96d56Sopenharmony_ci        CHILD.info(m())
3107db96d56Sopenharmony_ci
3117db96d56Sopenharmony_ci        # These should not log.
3127db96d56Sopenharmony_ci        GRANDCHILD.debug(m())
3137db96d56Sopenharmony_ci        CHILD.debug(m())
3147db96d56Sopenharmony_ci
3157db96d56Sopenharmony_ci        self.assert_log_lines([
3167db96d56Sopenharmony_ci            ('INF.BADPARENT.UNDEF', 'CRITICAL', '1'),
3177db96d56Sopenharmony_ci            ('INF.BADPARENT.UNDEF', 'INFO', '2'),
3187db96d56Sopenharmony_ci            ('INF.BADPARENT', 'CRITICAL', '3'),
3197db96d56Sopenharmony_ci            ('INF.BADPARENT', 'INFO', '4'),
3207db96d56Sopenharmony_ci        ])
3217db96d56Sopenharmony_ci
3227db96d56Sopenharmony_ci    def test_regression_22386(self):
3237db96d56Sopenharmony_ci        """See issue #22386 for more information."""
3247db96d56Sopenharmony_ci        self.assertEqual(logging.getLevelName('INFO'), logging.INFO)
3257db96d56Sopenharmony_ci        self.assertEqual(logging.getLevelName(logging.INFO), 'INFO')
3267db96d56Sopenharmony_ci
3277db96d56Sopenharmony_ci    def test_issue27935(self):
3287db96d56Sopenharmony_ci        fatal = logging.getLevelName('FATAL')
3297db96d56Sopenharmony_ci        self.assertEqual(fatal, logging.FATAL)
3307db96d56Sopenharmony_ci
3317db96d56Sopenharmony_ci    def test_regression_29220(self):
3327db96d56Sopenharmony_ci        """See issue #29220 for more information."""
3337db96d56Sopenharmony_ci        logging.addLevelName(logging.INFO, '')
3347db96d56Sopenharmony_ci        self.addCleanup(logging.addLevelName, logging.INFO, 'INFO')
3357db96d56Sopenharmony_ci        self.assertEqual(logging.getLevelName(logging.INFO), '')
3367db96d56Sopenharmony_ci        self.assertEqual(logging.getLevelName(logging.NOTSET), 'NOTSET')
3377db96d56Sopenharmony_ci        self.assertEqual(logging.getLevelName('NOTSET'), logging.NOTSET)
3387db96d56Sopenharmony_ci
3397db96d56Sopenharmony_ciclass BasicFilterTest(BaseTest):
3407db96d56Sopenharmony_ci
3417db96d56Sopenharmony_ci    """Test the bundled Filter class."""
3427db96d56Sopenharmony_ci
3437db96d56Sopenharmony_ci    def test_filter(self):
3447db96d56Sopenharmony_ci        # Only messages satisfying the specified criteria pass through the
3457db96d56Sopenharmony_ci        #  filter.
3467db96d56Sopenharmony_ci        filter_ = logging.Filter("spam.eggs")
3477db96d56Sopenharmony_ci        handler = self.root_logger.handlers[0]
3487db96d56Sopenharmony_ci        try:
3497db96d56Sopenharmony_ci            handler.addFilter(filter_)
3507db96d56Sopenharmony_ci            spam = logging.getLogger("spam")
3517db96d56Sopenharmony_ci            spam_eggs = logging.getLogger("spam.eggs")
3527db96d56Sopenharmony_ci            spam_eggs_fish = logging.getLogger("spam.eggs.fish")
3537db96d56Sopenharmony_ci            spam_bakedbeans = logging.getLogger("spam.bakedbeans")
3547db96d56Sopenharmony_ci
3557db96d56Sopenharmony_ci            spam.info(self.next_message())
3567db96d56Sopenharmony_ci            spam_eggs.info(self.next_message())  # Good.
3577db96d56Sopenharmony_ci            spam_eggs_fish.info(self.next_message())  # Good.
3587db96d56Sopenharmony_ci            spam_bakedbeans.info(self.next_message())
3597db96d56Sopenharmony_ci
3607db96d56Sopenharmony_ci            self.assert_log_lines([
3617db96d56Sopenharmony_ci                ('spam.eggs', 'INFO', '2'),
3627db96d56Sopenharmony_ci                ('spam.eggs.fish', 'INFO', '3'),
3637db96d56Sopenharmony_ci            ])
3647db96d56Sopenharmony_ci        finally:
3657db96d56Sopenharmony_ci            handler.removeFilter(filter_)
3667db96d56Sopenharmony_ci
3677db96d56Sopenharmony_ci    def test_callable_filter(self):
3687db96d56Sopenharmony_ci        # Only messages satisfying the specified criteria pass through the
3697db96d56Sopenharmony_ci        #  filter.
3707db96d56Sopenharmony_ci
3717db96d56Sopenharmony_ci        def filterfunc(record):
3727db96d56Sopenharmony_ci            parts = record.name.split('.')
3737db96d56Sopenharmony_ci            prefix = '.'.join(parts[:2])
3747db96d56Sopenharmony_ci            return prefix == 'spam.eggs'
3757db96d56Sopenharmony_ci
3767db96d56Sopenharmony_ci        handler = self.root_logger.handlers[0]
3777db96d56Sopenharmony_ci        try:
3787db96d56Sopenharmony_ci            handler.addFilter(filterfunc)
3797db96d56Sopenharmony_ci            spam = logging.getLogger("spam")
3807db96d56Sopenharmony_ci            spam_eggs = logging.getLogger("spam.eggs")
3817db96d56Sopenharmony_ci            spam_eggs_fish = logging.getLogger("spam.eggs.fish")
3827db96d56Sopenharmony_ci            spam_bakedbeans = logging.getLogger("spam.bakedbeans")
3837db96d56Sopenharmony_ci
3847db96d56Sopenharmony_ci            spam.info(self.next_message())
3857db96d56Sopenharmony_ci            spam_eggs.info(self.next_message())  # Good.
3867db96d56Sopenharmony_ci            spam_eggs_fish.info(self.next_message())  # Good.
3877db96d56Sopenharmony_ci            spam_bakedbeans.info(self.next_message())
3887db96d56Sopenharmony_ci
3897db96d56Sopenharmony_ci            self.assert_log_lines([
3907db96d56Sopenharmony_ci                ('spam.eggs', 'INFO', '2'),
3917db96d56Sopenharmony_ci                ('spam.eggs.fish', 'INFO', '3'),
3927db96d56Sopenharmony_ci            ])
3937db96d56Sopenharmony_ci        finally:
3947db96d56Sopenharmony_ci            handler.removeFilter(filterfunc)
3957db96d56Sopenharmony_ci
3967db96d56Sopenharmony_ci    def test_empty_filter(self):
3977db96d56Sopenharmony_ci        f = logging.Filter()
3987db96d56Sopenharmony_ci        r = logging.makeLogRecord({'name': 'spam.eggs'})
3997db96d56Sopenharmony_ci        self.assertTrue(f.filter(r))
4007db96d56Sopenharmony_ci
4017db96d56Sopenharmony_ci#
4027db96d56Sopenharmony_ci#   First, we define our levels. There can be as many as you want - the only
4037db96d56Sopenharmony_ci#     limitations are that they should be integers, the lowest should be > 0 and
4047db96d56Sopenharmony_ci#   larger values mean less information being logged. If you need specific
4057db96d56Sopenharmony_ci#   level values which do not fit into these limitations, you can use a
4067db96d56Sopenharmony_ci#   mapping dictionary to convert between your application levels and the
4077db96d56Sopenharmony_ci#   logging system.
4087db96d56Sopenharmony_ci#
4097db96d56Sopenharmony_ciSILENT      = 120
4107db96d56Sopenharmony_ciTACITURN    = 119
4117db96d56Sopenharmony_ciTERSE       = 118
4127db96d56Sopenharmony_ciEFFUSIVE    = 117
4137db96d56Sopenharmony_ciSOCIABLE    = 116
4147db96d56Sopenharmony_ciVERBOSE     = 115
4157db96d56Sopenharmony_ciTALKATIVE   = 114
4167db96d56Sopenharmony_ciGARRULOUS   = 113
4177db96d56Sopenharmony_ciCHATTERBOX  = 112
4187db96d56Sopenharmony_ciBORING      = 111
4197db96d56Sopenharmony_ci
4207db96d56Sopenharmony_ciLEVEL_RANGE = range(BORING, SILENT + 1)
4217db96d56Sopenharmony_ci
4227db96d56Sopenharmony_ci#
4237db96d56Sopenharmony_ci#   Next, we define names for our levels. You don't need to do this - in which
4247db96d56Sopenharmony_ci#   case the system will use "Level n" to denote the text for the level.
4257db96d56Sopenharmony_ci#
4267db96d56Sopenharmony_cimy_logging_levels = {
4277db96d56Sopenharmony_ci    SILENT      : 'Silent',
4287db96d56Sopenharmony_ci    TACITURN    : 'Taciturn',
4297db96d56Sopenharmony_ci    TERSE       : 'Terse',
4307db96d56Sopenharmony_ci    EFFUSIVE    : 'Effusive',
4317db96d56Sopenharmony_ci    SOCIABLE    : 'Sociable',
4327db96d56Sopenharmony_ci    VERBOSE     : 'Verbose',
4337db96d56Sopenharmony_ci    TALKATIVE   : 'Talkative',
4347db96d56Sopenharmony_ci    GARRULOUS   : 'Garrulous',
4357db96d56Sopenharmony_ci    CHATTERBOX  : 'Chatterbox',
4367db96d56Sopenharmony_ci    BORING      : 'Boring',
4377db96d56Sopenharmony_ci}
4387db96d56Sopenharmony_ci
4397db96d56Sopenharmony_ciclass GarrulousFilter(logging.Filter):
4407db96d56Sopenharmony_ci
4417db96d56Sopenharmony_ci    """A filter which blocks garrulous messages."""
4427db96d56Sopenharmony_ci
4437db96d56Sopenharmony_ci    def filter(self, record):
4447db96d56Sopenharmony_ci        return record.levelno != GARRULOUS
4457db96d56Sopenharmony_ci
4467db96d56Sopenharmony_ciclass VerySpecificFilter(logging.Filter):
4477db96d56Sopenharmony_ci
4487db96d56Sopenharmony_ci    """A filter which blocks sociable and taciturn messages."""
4497db96d56Sopenharmony_ci
4507db96d56Sopenharmony_ci    def filter(self, record):
4517db96d56Sopenharmony_ci        return record.levelno not in [SOCIABLE, TACITURN]
4527db96d56Sopenharmony_ci
4537db96d56Sopenharmony_ci
4547db96d56Sopenharmony_ciclass CustomLevelsAndFiltersTest(BaseTest):
4557db96d56Sopenharmony_ci
4567db96d56Sopenharmony_ci    """Test various filtering possibilities with custom logging levels."""
4577db96d56Sopenharmony_ci
4587db96d56Sopenharmony_ci    # Skip the logger name group.
4597db96d56Sopenharmony_ci    expected_log_pat = r"^[\w.]+ -> (\w+): (\d+)$"
4607db96d56Sopenharmony_ci
4617db96d56Sopenharmony_ci    def setUp(self):
4627db96d56Sopenharmony_ci        BaseTest.setUp(self)
4637db96d56Sopenharmony_ci        for k, v in my_logging_levels.items():
4647db96d56Sopenharmony_ci            logging.addLevelName(k, v)
4657db96d56Sopenharmony_ci
4667db96d56Sopenharmony_ci    def log_at_all_levels(self, logger):
4677db96d56Sopenharmony_ci        for lvl in LEVEL_RANGE:
4687db96d56Sopenharmony_ci            logger.log(lvl, self.next_message())
4697db96d56Sopenharmony_ci
4707db96d56Sopenharmony_ci    def test_logger_filter(self):
4717db96d56Sopenharmony_ci        # Filter at logger level.
4727db96d56Sopenharmony_ci        self.root_logger.setLevel(VERBOSE)
4737db96d56Sopenharmony_ci        # Levels >= 'Verbose' are good.
4747db96d56Sopenharmony_ci        self.log_at_all_levels(self.root_logger)
4757db96d56Sopenharmony_ci        self.assert_log_lines([
4767db96d56Sopenharmony_ci            ('Verbose', '5'),
4777db96d56Sopenharmony_ci            ('Sociable', '6'),
4787db96d56Sopenharmony_ci            ('Effusive', '7'),
4797db96d56Sopenharmony_ci            ('Terse', '8'),
4807db96d56Sopenharmony_ci            ('Taciturn', '9'),
4817db96d56Sopenharmony_ci            ('Silent', '10'),
4827db96d56Sopenharmony_ci        ])
4837db96d56Sopenharmony_ci
4847db96d56Sopenharmony_ci    def test_handler_filter(self):
4857db96d56Sopenharmony_ci        # Filter at handler level.
4867db96d56Sopenharmony_ci        self.root_logger.handlers[0].setLevel(SOCIABLE)
4877db96d56Sopenharmony_ci        try:
4887db96d56Sopenharmony_ci            # Levels >= 'Sociable' are good.
4897db96d56Sopenharmony_ci            self.log_at_all_levels(self.root_logger)
4907db96d56Sopenharmony_ci            self.assert_log_lines([
4917db96d56Sopenharmony_ci                ('Sociable', '6'),
4927db96d56Sopenharmony_ci                ('Effusive', '7'),
4937db96d56Sopenharmony_ci                ('Terse', '8'),
4947db96d56Sopenharmony_ci                ('Taciturn', '9'),
4957db96d56Sopenharmony_ci                ('Silent', '10'),
4967db96d56Sopenharmony_ci            ])
4977db96d56Sopenharmony_ci        finally:
4987db96d56Sopenharmony_ci            self.root_logger.handlers[0].setLevel(logging.NOTSET)
4997db96d56Sopenharmony_ci
5007db96d56Sopenharmony_ci    def test_specific_filters(self):
5017db96d56Sopenharmony_ci        # Set a specific filter object on the handler, and then add another
5027db96d56Sopenharmony_ci        #  filter object on the logger itself.
5037db96d56Sopenharmony_ci        handler = self.root_logger.handlers[0]
5047db96d56Sopenharmony_ci        specific_filter = None
5057db96d56Sopenharmony_ci        garr = GarrulousFilter()
5067db96d56Sopenharmony_ci        handler.addFilter(garr)
5077db96d56Sopenharmony_ci        try:
5087db96d56Sopenharmony_ci            self.log_at_all_levels(self.root_logger)
5097db96d56Sopenharmony_ci            first_lines = [
5107db96d56Sopenharmony_ci                # Notice how 'Garrulous' is missing
5117db96d56Sopenharmony_ci                ('Boring', '1'),
5127db96d56Sopenharmony_ci                ('Chatterbox', '2'),
5137db96d56Sopenharmony_ci                ('Talkative', '4'),
5147db96d56Sopenharmony_ci                ('Verbose', '5'),
5157db96d56Sopenharmony_ci                ('Sociable', '6'),
5167db96d56Sopenharmony_ci                ('Effusive', '7'),
5177db96d56Sopenharmony_ci                ('Terse', '8'),
5187db96d56Sopenharmony_ci                ('Taciturn', '9'),
5197db96d56Sopenharmony_ci                ('Silent', '10'),
5207db96d56Sopenharmony_ci            ]
5217db96d56Sopenharmony_ci            self.assert_log_lines(first_lines)
5227db96d56Sopenharmony_ci
5237db96d56Sopenharmony_ci            specific_filter = VerySpecificFilter()
5247db96d56Sopenharmony_ci            self.root_logger.addFilter(specific_filter)
5257db96d56Sopenharmony_ci            self.log_at_all_levels(self.root_logger)
5267db96d56Sopenharmony_ci            self.assert_log_lines(first_lines + [
5277db96d56Sopenharmony_ci                # Not only 'Garrulous' is still missing, but also 'Sociable'
5287db96d56Sopenharmony_ci                # and 'Taciturn'
5297db96d56Sopenharmony_ci                ('Boring', '11'),
5307db96d56Sopenharmony_ci                ('Chatterbox', '12'),
5317db96d56Sopenharmony_ci                ('Talkative', '14'),
5327db96d56Sopenharmony_ci                ('Verbose', '15'),
5337db96d56Sopenharmony_ci                ('Effusive', '17'),
5347db96d56Sopenharmony_ci                ('Terse', '18'),
5357db96d56Sopenharmony_ci                ('Silent', '20'),
5367db96d56Sopenharmony_ci        ])
5377db96d56Sopenharmony_ci        finally:
5387db96d56Sopenharmony_ci            if specific_filter:
5397db96d56Sopenharmony_ci                self.root_logger.removeFilter(specific_filter)
5407db96d56Sopenharmony_ci            handler.removeFilter(garr)
5417db96d56Sopenharmony_ci
5427db96d56Sopenharmony_ci
5437db96d56Sopenharmony_ciclass HandlerTest(BaseTest):
5447db96d56Sopenharmony_ci    def test_name(self):
5457db96d56Sopenharmony_ci        h = logging.Handler()
5467db96d56Sopenharmony_ci        h.name = 'generic'
5477db96d56Sopenharmony_ci        self.assertEqual(h.name, 'generic')
5487db96d56Sopenharmony_ci        h.name = 'anothergeneric'
5497db96d56Sopenharmony_ci        self.assertEqual(h.name, 'anothergeneric')
5507db96d56Sopenharmony_ci        self.assertRaises(NotImplementedError, h.emit, None)
5517db96d56Sopenharmony_ci
5527db96d56Sopenharmony_ci    def test_builtin_handlers(self):
5537db96d56Sopenharmony_ci        # We can't actually *use* too many handlers in the tests,
5547db96d56Sopenharmony_ci        # but we can try instantiating them with various options
5557db96d56Sopenharmony_ci        if sys.platform in ('linux', 'darwin'):
5567db96d56Sopenharmony_ci            for existing in (True, False):
5577db96d56Sopenharmony_ci                fd, fn = tempfile.mkstemp()
5587db96d56Sopenharmony_ci                os.close(fd)
5597db96d56Sopenharmony_ci                if not existing:
5607db96d56Sopenharmony_ci                    os.unlink(fn)
5617db96d56Sopenharmony_ci                h = logging.handlers.WatchedFileHandler(fn, encoding='utf-8', delay=True)
5627db96d56Sopenharmony_ci                if existing:
5637db96d56Sopenharmony_ci                    dev, ino = h.dev, h.ino
5647db96d56Sopenharmony_ci                    self.assertEqual(dev, -1)
5657db96d56Sopenharmony_ci                    self.assertEqual(ino, -1)
5667db96d56Sopenharmony_ci                    r = logging.makeLogRecord({'msg': 'Test'})
5677db96d56Sopenharmony_ci                    h.handle(r)
5687db96d56Sopenharmony_ci                    # Now remove the file.
5697db96d56Sopenharmony_ci                    os.unlink(fn)
5707db96d56Sopenharmony_ci                    self.assertFalse(os.path.exists(fn))
5717db96d56Sopenharmony_ci                    # The next call should recreate the file.
5727db96d56Sopenharmony_ci                    h.handle(r)
5737db96d56Sopenharmony_ci                    self.assertTrue(os.path.exists(fn))
5747db96d56Sopenharmony_ci                else:
5757db96d56Sopenharmony_ci                    self.assertEqual(h.dev, -1)
5767db96d56Sopenharmony_ci                    self.assertEqual(h.ino, -1)
5777db96d56Sopenharmony_ci                h.close()
5787db96d56Sopenharmony_ci                if existing:
5797db96d56Sopenharmony_ci                    os.unlink(fn)
5807db96d56Sopenharmony_ci            if sys.platform == 'darwin':
5817db96d56Sopenharmony_ci                sockname = '/var/run/syslog'
5827db96d56Sopenharmony_ci            else:
5837db96d56Sopenharmony_ci                sockname = '/dev/log'
5847db96d56Sopenharmony_ci            try:
5857db96d56Sopenharmony_ci                h = logging.handlers.SysLogHandler(sockname)
5867db96d56Sopenharmony_ci                self.assertEqual(h.facility, h.LOG_USER)
5877db96d56Sopenharmony_ci                self.assertTrue(h.unixsocket)
5887db96d56Sopenharmony_ci                h.close()
5897db96d56Sopenharmony_ci            except OSError: # syslogd might not be available
5907db96d56Sopenharmony_ci                pass
5917db96d56Sopenharmony_ci        for method in ('GET', 'POST', 'PUT'):
5927db96d56Sopenharmony_ci            if method == 'PUT':
5937db96d56Sopenharmony_ci                self.assertRaises(ValueError, logging.handlers.HTTPHandler,
5947db96d56Sopenharmony_ci                                  'localhost', '/log', method)
5957db96d56Sopenharmony_ci            else:
5967db96d56Sopenharmony_ci                h = logging.handlers.HTTPHandler('localhost', '/log', method)
5977db96d56Sopenharmony_ci                h.close()
5987db96d56Sopenharmony_ci        h = logging.handlers.BufferingHandler(0)
5997db96d56Sopenharmony_ci        r = logging.makeLogRecord({})
6007db96d56Sopenharmony_ci        self.assertTrue(h.shouldFlush(r))
6017db96d56Sopenharmony_ci        h.close()
6027db96d56Sopenharmony_ci        h = logging.handlers.BufferingHandler(1)
6037db96d56Sopenharmony_ci        self.assertFalse(h.shouldFlush(r))
6047db96d56Sopenharmony_ci        h.close()
6057db96d56Sopenharmony_ci
6067db96d56Sopenharmony_ci    def test_path_objects(self):
6077db96d56Sopenharmony_ci        """
6087db96d56Sopenharmony_ci        Test that Path objects are accepted as filename arguments to handlers.
6097db96d56Sopenharmony_ci
6107db96d56Sopenharmony_ci        See Issue #27493.
6117db96d56Sopenharmony_ci        """
6127db96d56Sopenharmony_ci        fd, fn = tempfile.mkstemp()
6137db96d56Sopenharmony_ci        os.close(fd)
6147db96d56Sopenharmony_ci        os.unlink(fn)
6157db96d56Sopenharmony_ci        pfn = pathlib.Path(fn)
6167db96d56Sopenharmony_ci        cases = (
6177db96d56Sopenharmony_ci                    (logging.FileHandler, (pfn, 'w')),
6187db96d56Sopenharmony_ci                    (logging.handlers.RotatingFileHandler, (pfn, 'a')),
6197db96d56Sopenharmony_ci                    (logging.handlers.TimedRotatingFileHandler, (pfn, 'h')),
6207db96d56Sopenharmony_ci                )
6217db96d56Sopenharmony_ci        if sys.platform in ('linux', 'darwin'):
6227db96d56Sopenharmony_ci            cases += ((logging.handlers.WatchedFileHandler, (pfn, 'w')),)
6237db96d56Sopenharmony_ci        for cls, args in cases:
6247db96d56Sopenharmony_ci            h = cls(*args, encoding="utf-8")
6257db96d56Sopenharmony_ci            self.assertTrue(os.path.exists(fn))
6267db96d56Sopenharmony_ci            h.close()
6277db96d56Sopenharmony_ci            os.unlink(fn)
6287db96d56Sopenharmony_ci
6297db96d56Sopenharmony_ci    @unittest.skipIf(os.name == 'nt', 'WatchedFileHandler not appropriate for Windows.')
6307db96d56Sopenharmony_ci    @unittest.skipIf(
6317db96d56Sopenharmony_ci        support.is_emscripten, "Emscripten cannot fstat unlinked files."
6327db96d56Sopenharmony_ci    )
6337db96d56Sopenharmony_ci    @threading_helper.requires_working_threading()
6347db96d56Sopenharmony_ci    def test_race(self):
6357db96d56Sopenharmony_ci        # Issue #14632 refers.
6367db96d56Sopenharmony_ci        def remove_loop(fname, tries):
6377db96d56Sopenharmony_ci            for _ in range(tries):
6387db96d56Sopenharmony_ci                try:
6397db96d56Sopenharmony_ci                    os.unlink(fname)
6407db96d56Sopenharmony_ci                    self.deletion_time = time.time()
6417db96d56Sopenharmony_ci                except OSError:
6427db96d56Sopenharmony_ci                    pass
6437db96d56Sopenharmony_ci                time.sleep(0.004 * random.randint(0, 4))
6447db96d56Sopenharmony_ci
6457db96d56Sopenharmony_ci        del_count = 500
6467db96d56Sopenharmony_ci        log_count = 500
6477db96d56Sopenharmony_ci
6487db96d56Sopenharmony_ci        self.handle_time = None
6497db96d56Sopenharmony_ci        self.deletion_time = None
6507db96d56Sopenharmony_ci
6517db96d56Sopenharmony_ci        for delay in (False, True):
6527db96d56Sopenharmony_ci            fd, fn = tempfile.mkstemp('.log', 'test_logging-3-')
6537db96d56Sopenharmony_ci            os.close(fd)
6547db96d56Sopenharmony_ci            remover = threading.Thread(target=remove_loop, args=(fn, del_count))
6557db96d56Sopenharmony_ci            remover.daemon = True
6567db96d56Sopenharmony_ci            remover.start()
6577db96d56Sopenharmony_ci            h = logging.handlers.WatchedFileHandler(fn, encoding='utf-8', delay=delay)
6587db96d56Sopenharmony_ci            f = logging.Formatter('%(asctime)s: %(levelname)s: %(message)s')
6597db96d56Sopenharmony_ci            h.setFormatter(f)
6607db96d56Sopenharmony_ci            try:
6617db96d56Sopenharmony_ci                for _ in range(log_count):
6627db96d56Sopenharmony_ci                    time.sleep(0.005)
6637db96d56Sopenharmony_ci                    r = logging.makeLogRecord({'msg': 'testing' })
6647db96d56Sopenharmony_ci                    try:
6657db96d56Sopenharmony_ci                        self.handle_time = time.time()
6667db96d56Sopenharmony_ci                        h.handle(r)
6677db96d56Sopenharmony_ci                    except Exception:
6687db96d56Sopenharmony_ci                        print('Deleted at %s, '
6697db96d56Sopenharmony_ci                              'opened at %s' % (self.deletion_time,
6707db96d56Sopenharmony_ci                                                self.handle_time))
6717db96d56Sopenharmony_ci                        raise
6727db96d56Sopenharmony_ci            finally:
6737db96d56Sopenharmony_ci                remover.join()
6747db96d56Sopenharmony_ci                h.close()
6757db96d56Sopenharmony_ci                if os.path.exists(fn):
6767db96d56Sopenharmony_ci                    os.unlink(fn)
6777db96d56Sopenharmony_ci
6787db96d56Sopenharmony_ci    # The implementation relies on os.register_at_fork existing, but we test
6797db96d56Sopenharmony_ci    # based on os.fork existing because that is what users and this test use.
6807db96d56Sopenharmony_ci    # This helps ensure that when fork exists (the important concept) that the
6817db96d56Sopenharmony_ci    # register_at_fork mechanism is also present and used.
6827db96d56Sopenharmony_ci    @support.requires_fork()
6837db96d56Sopenharmony_ci    @threading_helper.requires_working_threading()
6847db96d56Sopenharmony_ci    def test_post_fork_child_no_deadlock(self):
6857db96d56Sopenharmony_ci        """Ensure child logging locks are not held; bpo-6721 & bpo-36533."""
6867db96d56Sopenharmony_ci        class _OurHandler(logging.Handler):
6877db96d56Sopenharmony_ci            def __init__(self):
6887db96d56Sopenharmony_ci                super().__init__()
6897db96d56Sopenharmony_ci                self.sub_handler = logging.StreamHandler(
6907db96d56Sopenharmony_ci                    stream=open('/dev/null', 'wt', encoding='utf-8'))
6917db96d56Sopenharmony_ci
6927db96d56Sopenharmony_ci            def emit(self, record):
6937db96d56Sopenharmony_ci                self.sub_handler.acquire()
6947db96d56Sopenharmony_ci                try:
6957db96d56Sopenharmony_ci                    self.sub_handler.emit(record)
6967db96d56Sopenharmony_ci                finally:
6977db96d56Sopenharmony_ci                    self.sub_handler.release()
6987db96d56Sopenharmony_ci
6997db96d56Sopenharmony_ci        self.assertEqual(len(logging._handlers), 0)
7007db96d56Sopenharmony_ci        refed_h = _OurHandler()
7017db96d56Sopenharmony_ci        self.addCleanup(refed_h.sub_handler.stream.close)
7027db96d56Sopenharmony_ci        refed_h.name = 'because we need at least one for this test'
7037db96d56Sopenharmony_ci        self.assertGreater(len(logging._handlers), 0)
7047db96d56Sopenharmony_ci        self.assertGreater(len(logging._at_fork_reinit_lock_weakset), 1)
7057db96d56Sopenharmony_ci        test_logger = logging.getLogger('test_post_fork_child_no_deadlock')
7067db96d56Sopenharmony_ci        test_logger.addHandler(refed_h)
7077db96d56Sopenharmony_ci        test_logger.setLevel(logging.DEBUG)
7087db96d56Sopenharmony_ci
7097db96d56Sopenharmony_ci        locks_held__ready_to_fork = threading.Event()
7107db96d56Sopenharmony_ci        fork_happened__release_locks_and_end_thread = threading.Event()
7117db96d56Sopenharmony_ci
7127db96d56Sopenharmony_ci        def lock_holder_thread_fn():
7137db96d56Sopenharmony_ci            logging._acquireLock()
7147db96d56Sopenharmony_ci            try:
7157db96d56Sopenharmony_ci                refed_h.acquire()
7167db96d56Sopenharmony_ci                try:
7177db96d56Sopenharmony_ci                    # Tell the main thread to do the fork.
7187db96d56Sopenharmony_ci                    locks_held__ready_to_fork.set()
7197db96d56Sopenharmony_ci
7207db96d56Sopenharmony_ci                    # If the deadlock bug exists, the fork will happen
7217db96d56Sopenharmony_ci                    # without dealing with the locks we hold, deadlocking
7227db96d56Sopenharmony_ci                    # the child.
7237db96d56Sopenharmony_ci
7247db96d56Sopenharmony_ci                    # Wait for a successful fork or an unreasonable amount of
7257db96d56Sopenharmony_ci                    # time before releasing our locks.  To avoid a timing based
7267db96d56Sopenharmony_ci                    # test we'd need communication from os.fork() as to when it
7277db96d56Sopenharmony_ci                    # has actually happened.  Given this is a regression test
7287db96d56Sopenharmony_ci                    # for a fixed issue, potentially less reliably detecting
7297db96d56Sopenharmony_ci                    # regression via timing is acceptable for simplicity.
7307db96d56Sopenharmony_ci                    # The test will always take at least this long. :(
7317db96d56Sopenharmony_ci                    fork_happened__release_locks_and_end_thread.wait(0.5)
7327db96d56Sopenharmony_ci                finally:
7337db96d56Sopenharmony_ci                    refed_h.release()
7347db96d56Sopenharmony_ci            finally:
7357db96d56Sopenharmony_ci                logging._releaseLock()
7367db96d56Sopenharmony_ci
7377db96d56Sopenharmony_ci        lock_holder_thread = threading.Thread(
7387db96d56Sopenharmony_ci                target=lock_holder_thread_fn,
7397db96d56Sopenharmony_ci                name='test_post_fork_child_no_deadlock lock holder')
7407db96d56Sopenharmony_ci        lock_holder_thread.start()
7417db96d56Sopenharmony_ci
7427db96d56Sopenharmony_ci        locks_held__ready_to_fork.wait()
7437db96d56Sopenharmony_ci        pid = os.fork()
7447db96d56Sopenharmony_ci        if pid == 0:
7457db96d56Sopenharmony_ci            # Child process
7467db96d56Sopenharmony_ci            try:
7477db96d56Sopenharmony_ci                test_logger.info(r'Child process did not deadlock. \o/')
7487db96d56Sopenharmony_ci            finally:
7497db96d56Sopenharmony_ci                os._exit(0)
7507db96d56Sopenharmony_ci        else:
7517db96d56Sopenharmony_ci            # Parent process
7527db96d56Sopenharmony_ci            test_logger.info(r'Parent process returned from fork. \o/')
7537db96d56Sopenharmony_ci            fork_happened__release_locks_and_end_thread.set()
7547db96d56Sopenharmony_ci            lock_holder_thread.join()
7557db96d56Sopenharmony_ci
7567db96d56Sopenharmony_ci            support.wait_process(pid, exitcode=0)
7577db96d56Sopenharmony_ci
7587db96d56Sopenharmony_ci
7597db96d56Sopenharmony_ciclass BadStream(object):
7607db96d56Sopenharmony_ci    def write(self, data):
7617db96d56Sopenharmony_ci        raise RuntimeError('deliberate mistake')
7627db96d56Sopenharmony_ci
7637db96d56Sopenharmony_ciclass TestStreamHandler(logging.StreamHandler):
7647db96d56Sopenharmony_ci    def handleError(self, record):
7657db96d56Sopenharmony_ci        self.error_record = record
7667db96d56Sopenharmony_ci
7677db96d56Sopenharmony_ciclass StreamWithIntName(object):
7687db96d56Sopenharmony_ci    level = logging.NOTSET
7697db96d56Sopenharmony_ci    name = 2
7707db96d56Sopenharmony_ci
7717db96d56Sopenharmony_ciclass StreamHandlerTest(BaseTest):
7727db96d56Sopenharmony_ci    def test_error_handling(self):
7737db96d56Sopenharmony_ci        h = TestStreamHandler(BadStream())
7747db96d56Sopenharmony_ci        r = logging.makeLogRecord({})
7757db96d56Sopenharmony_ci        old_raise = logging.raiseExceptions
7767db96d56Sopenharmony_ci
7777db96d56Sopenharmony_ci        try:
7787db96d56Sopenharmony_ci            h.handle(r)
7797db96d56Sopenharmony_ci            self.assertIs(h.error_record, r)
7807db96d56Sopenharmony_ci
7817db96d56Sopenharmony_ci            h = logging.StreamHandler(BadStream())
7827db96d56Sopenharmony_ci            with support.captured_stderr() as stderr:
7837db96d56Sopenharmony_ci                h.handle(r)
7847db96d56Sopenharmony_ci                msg = '\nRuntimeError: deliberate mistake\n'
7857db96d56Sopenharmony_ci                self.assertIn(msg, stderr.getvalue())
7867db96d56Sopenharmony_ci
7877db96d56Sopenharmony_ci            logging.raiseExceptions = False
7887db96d56Sopenharmony_ci            with support.captured_stderr() as stderr:
7897db96d56Sopenharmony_ci                h.handle(r)
7907db96d56Sopenharmony_ci                self.assertEqual('', stderr.getvalue())
7917db96d56Sopenharmony_ci        finally:
7927db96d56Sopenharmony_ci            logging.raiseExceptions = old_raise
7937db96d56Sopenharmony_ci
7947db96d56Sopenharmony_ci    def test_stream_setting(self):
7957db96d56Sopenharmony_ci        """
7967db96d56Sopenharmony_ci        Test setting the handler's stream
7977db96d56Sopenharmony_ci        """
7987db96d56Sopenharmony_ci        h = logging.StreamHandler()
7997db96d56Sopenharmony_ci        stream = io.StringIO()
8007db96d56Sopenharmony_ci        old = h.setStream(stream)
8017db96d56Sopenharmony_ci        self.assertIs(old, sys.stderr)
8027db96d56Sopenharmony_ci        actual = h.setStream(old)
8037db96d56Sopenharmony_ci        self.assertIs(actual, stream)
8047db96d56Sopenharmony_ci        # test that setting to existing value returns None
8057db96d56Sopenharmony_ci        actual = h.setStream(old)
8067db96d56Sopenharmony_ci        self.assertIsNone(actual)
8077db96d56Sopenharmony_ci
8087db96d56Sopenharmony_ci    def test_can_represent_stream_with_int_name(self):
8097db96d56Sopenharmony_ci        h = logging.StreamHandler(StreamWithIntName())
8107db96d56Sopenharmony_ci        self.assertEqual(repr(h), '<StreamHandler 2 (NOTSET)>')
8117db96d56Sopenharmony_ci
8127db96d56Sopenharmony_ci# -- The following section could be moved into a server_helper.py module
8137db96d56Sopenharmony_ci# -- if it proves to be of wider utility than just test_logging
8147db96d56Sopenharmony_ci
8157db96d56Sopenharmony_ciclass TestSMTPServer(smtpd.SMTPServer):
8167db96d56Sopenharmony_ci    """
8177db96d56Sopenharmony_ci    This class implements a test SMTP server.
8187db96d56Sopenharmony_ci
8197db96d56Sopenharmony_ci    :param addr: A (host, port) tuple which the server listens on.
8207db96d56Sopenharmony_ci                 You can specify a port value of zero: the server's
8217db96d56Sopenharmony_ci                 *port* attribute will hold the actual port number
8227db96d56Sopenharmony_ci                 used, which can be used in client connections.
8237db96d56Sopenharmony_ci    :param handler: A callable which will be called to process
8247db96d56Sopenharmony_ci                    incoming messages. The handler will be passed
8257db96d56Sopenharmony_ci                    the client address tuple, who the message is from,
8267db96d56Sopenharmony_ci                    a list of recipients and the message data.
8277db96d56Sopenharmony_ci    :param poll_interval: The interval, in seconds, used in the underlying
8287db96d56Sopenharmony_ci                          :func:`select` or :func:`poll` call by
8297db96d56Sopenharmony_ci                          :func:`asyncore.loop`.
8307db96d56Sopenharmony_ci    :param sockmap: A dictionary which will be used to hold
8317db96d56Sopenharmony_ci                    :class:`asyncore.dispatcher` instances used by
8327db96d56Sopenharmony_ci                    :func:`asyncore.loop`. This avoids changing the
8337db96d56Sopenharmony_ci                    :mod:`asyncore` module's global state.
8347db96d56Sopenharmony_ci    """
8357db96d56Sopenharmony_ci
8367db96d56Sopenharmony_ci    def __init__(self, addr, handler, poll_interval, sockmap):
8377db96d56Sopenharmony_ci        smtpd.SMTPServer.__init__(self, addr, None, map=sockmap,
8387db96d56Sopenharmony_ci                                  decode_data=True)
8397db96d56Sopenharmony_ci        self.port = self.socket.getsockname()[1]
8407db96d56Sopenharmony_ci        self._handler = handler
8417db96d56Sopenharmony_ci        self._thread = None
8427db96d56Sopenharmony_ci        self._quit = False
8437db96d56Sopenharmony_ci        self.poll_interval = poll_interval
8447db96d56Sopenharmony_ci
8457db96d56Sopenharmony_ci    def process_message(self, peer, mailfrom, rcpttos, data):
8467db96d56Sopenharmony_ci        """
8477db96d56Sopenharmony_ci        Delegates to the handler passed in to the server's constructor.
8487db96d56Sopenharmony_ci
8497db96d56Sopenharmony_ci        Typically, this will be a test case method.
8507db96d56Sopenharmony_ci        :param peer: The client (host, port) tuple.
8517db96d56Sopenharmony_ci        :param mailfrom: The address of the sender.
8527db96d56Sopenharmony_ci        :param rcpttos: The addresses of the recipients.
8537db96d56Sopenharmony_ci        :param data: The message.
8547db96d56Sopenharmony_ci        """
8557db96d56Sopenharmony_ci        self._handler(peer, mailfrom, rcpttos, data)
8567db96d56Sopenharmony_ci
8577db96d56Sopenharmony_ci    def start(self):
8587db96d56Sopenharmony_ci        """
8597db96d56Sopenharmony_ci        Start the server running on a separate daemon thread.
8607db96d56Sopenharmony_ci        """
8617db96d56Sopenharmony_ci        self._thread = t = threading.Thread(target=self.serve_forever,
8627db96d56Sopenharmony_ci                                            args=(self.poll_interval,))
8637db96d56Sopenharmony_ci        t.daemon = True
8647db96d56Sopenharmony_ci        t.start()
8657db96d56Sopenharmony_ci
8667db96d56Sopenharmony_ci    def serve_forever(self, poll_interval):
8677db96d56Sopenharmony_ci        """
8687db96d56Sopenharmony_ci        Run the :mod:`asyncore` loop until normal termination
8697db96d56Sopenharmony_ci        conditions arise.
8707db96d56Sopenharmony_ci        :param poll_interval: The interval, in seconds, used in the underlying
8717db96d56Sopenharmony_ci                              :func:`select` or :func:`poll` call by
8727db96d56Sopenharmony_ci                              :func:`asyncore.loop`.
8737db96d56Sopenharmony_ci        """
8747db96d56Sopenharmony_ci        while not self._quit:
8757db96d56Sopenharmony_ci            asyncore.loop(poll_interval, map=self._map, count=1)
8767db96d56Sopenharmony_ci
8777db96d56Sopenharmony_ci    def stop(self):
8787db96d56Sopenharmony_ci        """
8797db96d56Sopenharmony_ci        Stop the thread by closing the server instance.
8807db96d56Sopenharmony_ci        Wait for the server thread to terminate.
8817db96d56Sopenharmony_ci        """
8827db96d56Sopenharmony_ci        self._quit = True
8837db96d56Sopenharmony_ci        threading_helper.join_thread(self._thread)
8847db96d56Sopenharmony_ci        self._thread = None
8857db96d56Sopenharmony_ci        self.close()
8867db96d56Sopenharmony_ci        asyncore.close_all(map=self._map, ignore_all=True)
8877db96d56Sopenharmony_ci
8887db96d56Sopenharmony_ci
8897db96d56Sopenharmony_ciclass ControlMixin(object):
8907db96d56Sopenharmony_ci    """
8917db96d56Sopenharmony_ci    This mixin is used to start a server on a separate thread, and
8927db96d56Sopenharmony_ci    shut it down programmatically. Request handling is simplified - instead
8937db96d56Sopenharmony_ci    of needing to derive a suitable RequestHandler subclass, you just
8947db96d56Sopenharmony_ci    provide a callable which will be passed each received request to be
8957db96d56Sopenharmony_ci    processed.
8967db96d56Sopenharmony_ci
8977db96d56Sopenharmony_ci    :param handler: A handler callable which will be called with a
8987db96d56Sopenharmony_ci                    single parameter - the request - in order to
8997db96d56Sopenharmony_ci                    process the request. This handler is called on the
9007db96d56Sopenharmony_ci                    server thread, effectively meaning that requests are
9017db96d56Sopenharmony_ci                    processed serially. While not quite web scale ;-),
9027db96d56Sopenharmony_ci                    this should be fine for testing applications.
9037db96d56Sopenharmony_ci    :param poll_interval: The polling interval in seconds.
9047db96d56Sopenharmony_ci    """
9057db96d56Sopenharmony_ci    def __init__(self, handler, poll_interval):
9067db96d56Sopenharmony_ci        self._thread = None
9077db96d56Sopenharmony_ci        self.poll_interval = poll_interval
9087db96d56Sopenharmony_ci        self._handler = handler
9097db96d56Sopenharmony_ci        self.ready = threading.Event()
9107db96d56Sopenharmony_ci
9117db96d56Sopenharmony_ci    def start(self):
9127db96d56Sopenharmony_ci        """
9137db96d56Sopenharmony_ci        Create a daemon thread to run the server, and start it.
9147db96d56Sopenharmony_ci        """
9157db96d56Sopenharmony_ci        self._thread = t = threading.Thread(target=self.serve_forever,
9167db96d56Sopenharmony_ci                                            args=(self.poll_interval,))
9177db96d56Sopenharmony_ci        t.daemon = True
9187db96d56Sopenharmony_ci        t.start()
9197db96d56Sopenharmony_ci
9207db96d56Sopenharmony_ci    def serve_forever(self, poll_interval):
9217db96d56Sopenharmony_ci        """
9227db96d56Sopenharmony_ci        Run the server. Set the ready flag before entering the
9237db96d56Sopenharmony_ci        service loop.
9247db96d56Sopenharmony_ci        """
9257db96d56Sopenharmony_ci        self.ready.set()
9267db96d56Sopenharmony_ci        super(ControlMixin, self).serve_forever(poll_interval)
9277db96d56Sopenharmony_ci
9287db96d56Sopenharmony_ci    def stop(self):
9297db96d56Sopenharmony_ci        """
9307db96d56Sopenharmony_ci        Tell the server thread to stop, and wait for it to do so.
9317db96d56Sopenharmony_ci        """
9327db96d56Sopenharmony_ci        self.shutdown()
9337db96d56Sopenharmony_ci        if self._thread is not None:
9347db96d56Sopenharmony_ci            threading_helper.join_thread(self._thread)
9357db96d56Sopenharmony_ci            self._thread = None
9367db96d56Sopenharmony_ci        self.server_close()
9377db96d56Sopenharmony_ci        self.ready.clear()
9387db96d56Sopenharmony_ci
9397db96d56Sopenharmony_ciclass TestHTTPServer(ControlMixin, HTTPServer):
9407db96d56Sopenharmony_ci    """
9417db96d56Sopenharmony_ci    An HTTP server which is controllable using :class:`ControlMixin`.
9427db96d56Sopenharmony_ci
9437db96d56Sopenharmony_ci    :param addr: A tuple with the IP address and port to listen on.
9447db96d56Sopenharmony_ci    :param handler: A handler callable which will be called with a
9457db96d56Sopenharmony_ci                    single parameter - the request - in order to
9467db96d56Sopenharmony_ci                    process the request.
9477db96d56Sopenharmony_ci    :param poll_interval: The polling interval in seconds.
9487db96d56Sopenharmony_ci    :param log: Pass ``True`` to enable log messages.
9497db96d56Sopenharmony_ci    """
9507db96d56Sopenharmony_ci    def __init__(self, addr, handler, poll_interval=0.5,
9517db96d56Sopenharmony_ci                 log=False, sslctx=None):
9527db96d56Sopenharmony_ci        class DelegatingHTTPRequestHandler(BaseHTTPRequestHandler):
9537db96d56Sopenharmony_ci            def __getattr__(self, name, default=None):
9547db96d56Sopenharmony_ci                if name.startswith('do_'):
9557db96d56Sopenharmony_ci                    return self.process_request
9567db96d56Sopenharmony_ci                raise AttributeError(name)
9577db96d56Sopenharmony_ci
9587db96d56Sopenharmony_ci            def process_request(self):
9597db96d56Sopenharmony_ci                self.server._handler(self)
9607db96d56Sopenharmony_ci
9617db96d56Sopenharmony_ci            def log_message(self, format, *args):
9627db96d56Sopenharmony_ci                if log:
9637db96d56Sopenharmony_ci                    super(DelegatingHTTPRequestHandler,
9647db96d56Sopenharmony_ci                          self).log_message(format, *args)
9657db96d56Sopenharmony_ci        HTTPServer.__init__(self, addr, DelegatingHTTPRequestHandler)
9667db96d56Sopenharmony_ci        ControlMixin.__init__(self, handler, poll_interval)
9677db96d56Sopenharmony_ci        self.sslctx = sslctx
9687db96d56Sopenharmony_ci
9697db96d56Sopenharmony_ci    def get_request(self):
9707db96d56Sopenharmony_ci        try:
9717db96d56Sopenharmony_ci            sock, addr = self.socket.accept()
9727db96d56Sopenharmony_ci            if self.sslctx:
9737db96d56Sopenharmony_ci                sock = self.sslctx.wrap_socket(sock, server_side=True)
9747db96d56Sopenharmony_ci        except OSError as e:
9757db96d56Sopenharmony_ci            # socket errors are silenced by the caller, print them here
9767db96d56Sopenharmony_ci            sys.stderr.write("Got an error:\n%s\n" % e)
9777db96d56Sopenharmony_ci            raise
9787db96d56Sopenharmony_ci        return sock, addr
9797db96d56Sopenharmony_ci
9807db96d56Sopenharmony_ciclass TestTCPServer(ControlMixin, ThreadingTCPServer):
9817db96d56Sopenharmony_ci    """
9827db96d56Sopenharmony_ci    A TCP server which is controllable using :class:`ControlMixin`.
9837db96d56Sopenharmony_ci
9847db96d56Sopenharmony_ci    :param addr: A tuple with the IP address and port to listen on.
9857db96d56Sopenharmony_ci    :param handler: A handler callable which will be called with a single
9867db96d56Sopenharmony_ci                    parameter - the request - in order to process the request.
9877db96d56Sopenharmony_ci    :param poll_interval: The polling interval in seconds.
9887db96d56Sopenharmony_ci    :bind_and_activate: If True (the default), binds the server and starts it
9897db96d56Sopenharmony_ci                        listening. If False, you need to call
9907db96d56Sopenharmony_ci                        :meth:`server_bind` and :meth:`server_activate` at
9917db96d56Sopenharmony_ci                        some later time before calling :meth:`start`, so that
9927db96d56Sopenharmony_ci                        the server will set up the socket and listen on it.
9937db96d56Sopenharmony_ci    """
9947db96d56Sopenharmony_ci
9957db96d56Sopenharmony_ci    allow_reuse_address = True
9967db96d56Sopenharmony_ci
9977db96d56Sopenharmony_ci    def __init__(self, addr, handler, poll_interval=0.5,
9987db96d56Sopenharmony_ci                 bind_and_activate=True):
9997db96d56Sopenharmony_ci        class DelegatingTCPRequestHandler(StreamRequestHandler):
10007db96d56Sopenharmony_ci
10017db96d56Sopenharmony_ci            def handle(self):
10027db96d56Sopenharmony_ci                self.server._handler(self)
10037db96d56Sopenharmony_ci        ThreadingTCPServer.__init__(self, addr, DelegatingTCPRequestHandler,
10047db96d56Sopenharmony_ci                                    bind_and_activate)
10057db96d56Sopenharmony_ci        ControlMixin.__init__(self, handler, poll_interval)
10067db96d56Sopenharmony_ci
10077db96d56Sopenharmony_ci    def server_bind(self):
10087db96d56Sopenharmony_ci        super(TestTCPServer, self).server_bind()
10097db96d56Sopenharmony_ci        self.port = self.socket.getsockname()[1]
10107db96d56Sopenharmony_ci
10117db96d56Sopenharmony_ciclass TestUDPServer(ControlMixin, ThreadingUDPServer):
10127db96d56Sopenharmony_ci    """
10137db96d56Sopenharmony_ci    A UDP server which is controllable using :class:`ControlMixin`.
10147db96d56Sopenharmony_ci
10157db96d56Sopenharmony_ci    :param addr: A tuple with the IP address and port to listen on.
10167db96d56Sopenharmony_ci    :param handler: A handler callable which will be called with a
10177db96d56Sopenharmony_ci                    single parameter - the request - in order to
10187db96d56Sopenharmony_ci                    process the request.
10197db96d56Sopenharmony_ci    :param poll_interval: The polling interval for shutdown requests,
10207db96d56Sopenharmony_ci                          in seconds.
10217db96d56Sopenharmony_ci    :bind_and_activate: If True (the default), binds the server and
10227db96d56Sopenharmony_ci                        starts it listening. If False, you need to
10237db96d56Sopenharmony_ci                        call :meth:`server_bind` and
10247db96d56Sopenharmony_ci                        :meth:`server_activate` at some later time
10257db96d56Sopenharmony_ci                        before calling :meth:`start`, so that the server will
10267db96d56Sopenharmony_ci                        set up the socket and listen on it.
10277db96d56Sopenharmony_ci    """
10287db96d56Sopenharmony_ci    def __init__(self, addr, handler, poll_interval=0.5,
10297db96d56Sopenharmony_ci                 bind_and_activate=True):
10307db96d56Sopenharmony_ci        class DelegatingUDPRequestHandler(DatagramRequestHandler):
10317db96d56Sopenharmony_ci
10327db96d56Sopenharmony_ci            def handle(self):
10337db96d56Sopenharmony_ci                self.server._handler(self)
10347db96d56Sopenharmony_ci
10357db96d56Sopenharmony_ci            def finish(self):
10367db96d56Sopenharmony_ci                data = self.wfile.getvalue()
10377db96d56Sopenharmony_ci                if data:
10387db96d56Sopenharmony_ci                    try:
10397db96d56Sopenharmony_ci                        super(DelegatingUDPRequestHandler, self).finish()
10407db96d56Sopenharmony_ci                    except OSError:
10417db96d56Sopenharmony_ci                        if not self.server._closed:
10427db96d56Sopenharmony_ci                            raise
10437db96d56Sopenharmony_ci
10447db96d56Sopenharmony_ci        ThreadingUDPServer.__init__(self, addr,
10457db96d56Sopenharmony_ci                                    DelegatingUDPRequestHandler,
10467db96d56Sopenharmony_ci                                    bind_and_activate)
10477db96d56Sopenharmony_ci        ControlMixin.__init__(self, handler, poll_interval)
10487db96d56Sopenharmony_ci        self._closed = False
10497db96d56Sopenharmony_ci
10507db96d56Sopenharmony_ci    def server_bind(self):
10517db96d56Sopenharmony_ci        super(TestUDPServer, self).server_bind()
10527db96d56Sopenharmony_ci        self.port = self.socket.getsockname()[1]
10537db96d56Sopenharmony_ci
10547db96d56Sopenharmony_ci    def server_close(self):
10557db96d56Sopenharmony_ci        super(TestUDPServer, self).server_close()
10567db96d56Sopenharmony_ci        self._closed = True
10577db96d56Sopenharmony_ci
10587db96d56Sopenharmony_ciif hasattr(socket, "AF_UNIX"):
10597db96d56Sopenharmony_ci    class TestUnixStreamServer(TestTCPServer):
10607db96d56Sopenharmony_ci        address_family = socket.AF_UNIX
10617db96d56Sopenharmony_ci
10627db96d56Sopenharmony_ci    class TestUnixDatagramServer(TestUDPServer):
10637db96d56Sopenharmony_ci        address_family = socket.AF_UNIX
10647db96d56Sopenharmony_ci
10657db96d56Sopenharmony_ci# - end of server_helper section
10667db96d56Sopenharmony_ci
10677db96d56Sopenharmony_ci@support.requires_working_socket()
10687db96d56Sopenharmony_ci@threading_helper.requires_working_threading()
10697db96d56Sopenharmony_ciclass SMTPHandlerTest(BaseTest):
10707db96d56Sopenharmony_ci    # bpo-14314, bpo-19665, bpo-34092: don't wait forever
10717db96d56Sopenharmony_ci    TIMEOUT = support.LONG_TIMEOUT
10727db96d56Sopenharmony_ci
10737db96d56Sopenharmony_ci    def test_basic(self):
10747db96d56Sopenharmony_ci        sockmap = {}
10757db96d56Sopenharmony_ci        server = TestSMTPServer((socket_helper.HOST, 0), self.process_message, 0.001,
10767db96d56Sopenharmony_ci                                sockmap)
10777db96d56Sopenharmony_ci        server.start()
10787db96d56Sopenharmony_ci        addr = (socket_helper.HOST, server.port)
10797db96d56Sopenharmony_ci        h = logging.handlers.SMTPHandler(addr, 'me', 'you', 'Log',
10807db96d56Sopenharmony_ci                                         timeout=self.TIMEOUT)
10817db96d56Sopenharmony_ci        self.assertEqual(h.toaddrs, ['you'])
10827db96d56Sopenharmony_ci        self.messages = []
10837db96d56Sopenharmony_ci        r = logging.makeLogRecord({'msg': 'Hello \u2713'})
10847db96d56Sopenharmony_ci        self.handled = threading.Event()
10857db96d56Sopenharmony_ci        h.handle(r)
10867db96d56Sopenharmony_ci        self.handled.wait(self.TIMEOUT)
10877db96d56Sopenharmony_ci        server.stop()
10887db96d56Sopenharmony_ci        self.assertTrue(self.handled.is_set())
10897db96d56Sopenharmony_ci        self.assertEqual(len(self.messages), 1)
10907db96d56Sopenharmony_ci        peer, mailfrom, rcpttos, data = self.messages[0]
10917db96d56Sopenharmony_ci        self.assertEqual(mailfrom, 'me')
10927db96d56Sopenharmony_ci        self.assertEqual(rcpttos, ['you'])
10937db96d56Sopenharmony_ci        self.assertIn('\nSubject: Log\n', data)
10947db96d56Sopenharmony_ci        self.assertTrue(data.endswith('\n\nHello \u2713'))
10957db96d56Sopenharmony_ci        h.close()
10967db96d56Sopenharmony_ci
10977db96d56Sopenharmony_ci    def process_message(self, *args):
10987db96d56Sopenharmony_ci        self.messages.append(args)
10997db96d56Sopenharmony_ci        self.handled.set()
11007db96d56Sopenharmony_ci
11017db96d56Sopenharmony_ciclass MemoryHandlerTest(BaseTest):
11027db96d56Sopenharmony_ci
11037db96d56Sopenharmony_ci    """Tests for the MemoryHandler."""
11047db96d56Sopenharmony_ci
11057db96d56Sopenharmony_ci    # Do not bother with a logger name group.
11067db96d56Sopenharmony_ci    expected_log_pat = r"^[\w.]+ -> (\w+): (\d+)$"
11077db96d56Sopenharmony_ci
11087db96d56Sopenharmony_ci    def setUp(self):
11097db96d56Sopenharmony_ci        BaseTest.setUp(self)
11107db96d56Sopenharmony_ci        self.mem_hdlr = logging.handlers.MemoryHandler(10, logging.WARNING,
11117db96d56Sopenharmony_ci                                                       self.root_hdlr)
11127db96d56Sopenharmony_ci        self.mem_logger = logging.getLogger('mem')
11137db96d56Sopenharmony_ci        self.mem_logger.propagate = 0
11147db96d56Sopenharmony_ci        self.mem_logger.addHandler(self.mem_hdlr)
11157db96d56Sopenharmony_ci
11167db96d56Sopenharmony_ci    def tearDown(self):
11177db96d56Sopenharmony_ci        self.mem_hdlr.close()
11187db96d56Sopenharmony_ci        BaseTest.tearDown(self)
11197db96d56Sopenharmony_ci
11207db96d56Sopenharmony_ci    def test_flush(self):
11217db96d56Sopenharmony_ci        # The memory handler flushes to its target handler based on specific
11227db96d56Sopenharmony_ci        #  criteria (message count and message level).
11237db96d56Sopenharmony_ci        self.mem_logger.debug(self.next_message())
11247db96d56Sopenharmony_ci        self.assert_log_lines([])
11257db96d56Sopenharmony_ci        self.mem_logger.info(self.next_message())
11267db96d56Sopenharmony_ci        self.assert_log_lines([])
11277db96d56Sopenharmony_ci        # This will flush because the level is >= logging.WARNING
11287db96d56Sopenharmony_ci        self.mem_logger.warning(self.next_message())
11297db96d56Sopenharmony_ci        lines = [
11307db96d56Sopenharmony_ci            ('DEBUG', '1'),
11317db96d56Sopenharmony_ci            ('INFO', '2'),
11327db96d56Sopenharmony_ci            ('WARNING', '3'),
11337db96d56Sopenharmony_ci        ]
11347db96d56Sopenharmony_ci        self.assert_log_lines(lines)
11357db96d56Sopenharmony_ci        for n in (4, 14):
11367db96d56Sopenharmony_ci            for i in range(9):
11377db96d56Sopenharmony_ci                self.mem_logger.debug(self.next_message())
11387db96d56Sopenharmony_ci            self.assert_log_lines(lines)
11397db96d56Sopenharmony_ci            # This will flush because it's the 10th message since the last
11407db96d56Sopenharmony_ci            #  flush.
11417db96d56Sopenharmony_ci            self.mem_logger.debug(self.next_message())
11427db96d56Sopenharmony_ci            lines = lines + [('DEBUG', str(i)) for i in range(n, n + 10)]
11437db96d56Sopenharmony_ci            self.assert_log_lines(lines)
11447db96d56Sopenharmony_ci
11457db96d56Sopenharmony_ci        self.mem_logger.debug(self.next_message())
11467db96d56Sopenharmony_ci        self.assert_log_lines(lines)
11477db96d56Sopenharmony_ci
11487db96d56Sopenharmony_ci    def test_flush_on_close(self):
11497db96d56Sopenharmony_ci        """
11507db96d56Sopenharmony_ci        Test that the flush-on-close configuration works as expected.
11517db96d56Sopenharmony_ci        """
11527db96d56Sopenharmony_ci        self.mem_logger.debug(self.next_message())
11537db96d56Sopenharmony_ci        self.assert_log_lines([])
11547db96d56Sopenharmony_ci        self.mem_logger.info(self.next_message())
11557db96d56Sopenharmony_ci        self.assert_log_lines([])
11567db96d56Sopenharmony_ci        self.mem_logger.removeHandler(self.mem_hdlr)
11577db96d56Sopenharmony_ci        # Default behaviour is to flush on close. Check that it happens.
11587db96d56Sopenharmony_ci        self.mem_hdlr.close()
11597db96d56Sopenharmony_ci        lines = [
11607db96d56Sopenharmony_ci            ('DEBUG', '1'),
11617db96d56Sopenharmony_ci            ('INFO', '2'),
11627db96d56Sopenharmony_ci        ]
11637db96d56Sopenharmony_ci        self.assert_log_lines(lines)
11647db96d56Sopenharmony_ci        # Now configure for flushing not to be done on close.
11657db96d56Sopenharmony_ci        self.mem_hdlr = logging.handlers.MemoryHandler(10, logging.WARNING,
11667db96d56Sopenharmony_ci                                                       self.root_hdlr,
11677db96d56Sopenharmony_ci                                                       False)
11687db96d56Sopenharmony_ci        self.mem_logger.addHandler(self.mem_hdlr)
11697db96d56Sopenharmony_ci        self.mem_logger.debug(self.next_message())
11707db96d56Sopenharmony_ci        self.assert_log_lines(lines)  # no change
11717db96d56Sopenharmony_ci        self.mem_logger.info(self.next_message())
11727db96d56Sopenharmony_ci        self.assert_log_lines(lines)  # no change
11737db96d56Sopenharmony_ci        self.mem_logger.removeHandler(self.mem_hdlr)
11747db96d56Sopenharmony_ci        self.mem_hdlr.close()
11757db96d56Sopenharmony_ci        # assert that no new lines have been added
11767db96d56Sopenharmony_ci        self.assert_log_lines(lines)  # no change
11777db96d56Sopenharmony_ci
11787db96d56Sopenharmony_ci    @threading_helper.requires_working_threading()
11797db96d56Sopenharmony_ci    def test_race_between_set_target_and_flush(self):
11807db96d56Sopenharmony_ci        class MockRaceConditionHandler:
11817db96d56Sopenharmony_ci            def __init__(self, mem_hdlr):
11827db96d56Sopenharmony_ci                self.mem_hdlr = mem_hdlr
11837db96d56Sopenharmony_ci                self.threads = []
11847db96d56Sopenharmony_ci
11857db96d56Sopenharmony_ci            def removeTarget(self):
11867db96d56Sopenharmony_ci                self.mem_hdlr.setTarget(None)
11877db96d56Sopenharmony_ci
11887db96d56Sopenharmony_ci            def handle(self, msg):
11897db96d56Sopenharmony_ci                thread = threading.Thread(target=self.removeTarget)
11907db96d56Sopenharmony_ci                self.threads.append(thread)
11917db96d56Sopenharmony_ci                thread.start()
11927db96d56Sopenharmony_ci
11937db96d56Sopenharmony_ci        target = MockRaceConditionHandler(self.mem_hdlr)
11947db96d56Sopenharmony_ci        try:
11957db96d56Sopenharmony_ci            self.mem_hdlr.setTarget(target)
11967db96d56Sopenharmony_ci
11977db96d56Sopenharmony_ci            for _ in range(10):
11987db96d56Sopenharmony_ci                time.sleep(0.005)
11997db96d56Sopenharmony_ci                self.mem_logger.info("not flushed")
12007db96d56Sopenharmony_ci                self.mem_logger.warning("flushed")
12017db96d56Sopenharmony_ci        finally:
12027db96d56Sopenharmony_ci            for thread in target.threads:
12037db96d56Sopenharmony_ci                threading_helper.join_thread(thread)
12047db96d56Sopenharmony_ci
12057db96d56Sopenharmony_ci
12067db96d56Sopenharmony_ciclass ExceptionFormatter(logging.Formatter):
12077db96d56Sopenharmony_ci    """A special exception formatter."""
12087db96d56Sopenharmony_ci    def formatException(self, ei):
12097db96d56Sopenharmony_ci        return "Got a [%s]" % ei[0].__name__
12107db96d56Sopenharmony_ci
12117db96d56Sopenharmony_ci
12127db96d56Sopenharmony_ciclass ConfigFileTest(BaseTest):
12137db96d56Sopenharmony_ci
12147db96d56Sopenharmony_ci    """Reading logging config from a .ini-style config file."""
12157db96d56Sopenharmony_ci
12167db96d56Sopenharmony_ci    check_no_resource_warning = warnings_helper.check_no_resource_warning
12177db96d56Sopenharmony_ci    expected_log_pat = r"^(\w+) \+\+ (\w+)$"
12187db96d56Sopenharmony_ci
12197db96d56Sopenharmony_ci    # config0 is a standard configuration.
12207db96d56Sopenharmony_ci    config0 = """
12217db96d56Sopenharmony_ci    [loggers]
12227db96d56Sopenharmony_ci    keys=root
12237db96d56Sopenharmony_ci
12247db96d56Sopenharmony_ci    [handlers]
12257db96d56Sopenharmony_ci    keys=hand1
12267db96d56Sopenharmony_ci
12277db96d56Sopenharmony_ci    [formatters]
12287db96d56Sopenharmony_ci    keys=form1
12297db96d56Sopenharmony_ci
12307db96d56Sopenharmony_ci    [logger_root]
12317db96d56Sopenharmony_ci    level=WARNING
12327db96d56Sopenharmony_ci    handlers=hand1
12337db96d56Sopenharmony_ci
12347db96d56Sopenharmony_ci    [handler_hand1]
12357db96d56Sopenharmony_ci    class=StreamHandler
12367db96d56Sopenharmony_ci    level=NOTSET
12377db96d56Sopenharmony_ci    formatter=form1
12387db96d56Sopenharmony_ci    args=(sys.stdout,)
12397db96d56Sopenharmony_ci
12407db96d56Sopenharmony_ci    [formatter_form1]
12417db96d56Sopenharmony_ci    format=%(levelname)s ++ %(message)s
12427db96d56Sopenharmony_ci    datefmt=
12437db96d56Sopenharmony_ci    """
12447db96d56Sopenharmony_ci
12457db96d56Sopenharmony_ci    # config1 adds a little to the standard configuration.
12467db96d56Sopenharmony_ci    config1 = """
12477db96d56Sopenharmony_ci    [loggers]
12487db96d56Sopenharmony_ci    keys=root,parser
12497db96d56Sopenharmony_ci
12507db96d56Sopenharmony_ci    [handlers]
12517db96d56Sopenharmony_ci    keys=hand1
12527db96d56Sopenharmony_ci
12537db96d56Sopenharmony_ci    [formatters]
12547db96d56Sopenharmony_ci    keys=form1
12557db96d56Sopenharmony_ci
12567db96d56Sopenharmony_ci    [logger_root]
12577db96d56Sopenharmony_ci    level=WARNING
12587db96d56Sopenharmony_ci    handlers=
12597db96d56Sopenharmony_ci
12607db96d56Sopenharmony_ci    [logger_parser]
12617db96d56Sopenharmony_ci    level=DEBUG
12627db96d56Sopenharmony_ci    handlers=hand1
12637db96d56Sopenharmony_ci    propagate=1
12647db96d56Sopenharmony_ci    qualname=compiler.parser
12657db96d56Sopenharmony_ci
12667db96d56Sopenharmony_ci    [handler_hand1]
12677db96d56Sopenharmony_ci    class=StreamHandler
12687db96d56Sopenharmony_ci    level=NOTSET
12697db96d56Sopenharmony_ci    formatter=form1
12707db96d56Sopenharmony_ci    args=(sys.stdout,)
12717db96d56Sopenharmony_ci
12727db96d56Sopenharmony_ci    [formatter_form1]
12737db96d56Sopenharmony_ci    format=%(levelname)s ++ %(message)s
12747db96d56Sopenharmony_ci    datefmt=
12757db96d56Sopenharmony_ci    """
12767db96d56Sopenharmony_ci
12777db96d56Sopenharmony_ci    # config1a moves the handler to the root.
12787db96d56Sopenharmony_ci    config1a = """
12797db96d56Sopenharmony_ci    [loggers]
12807db96d56Sopenharmony_ci    keys=root,parser
12817db96d56Sopenharmony_ci
12827db96d56Sopenharmony_ci    [handlers]
12837db96d56Sopenharmony_ci    keys=hand1
12847db96d56Sopenharmony_ci
12857db96d56Sopenharmony_ci    [formatters]
12867db96d56Sopenharmony_ci    keys=form1
12877db96d56Sopenharmony_ci
12887db96d56Sopenharmony_ci    [logger_root]
12897db96d56Sopenharmony_ci    level=WARNING
12907db96d56Sopenharmony_ci    handlers=hand1
12917db96d56Sopenharmony_ci
12927db96d56Sopenharmony_ci    [logger_parser]
12937db96d56Sopenharmony_ci    level=DEBUG
12947db96d56Sopenharmony_ci    handlers=
12957db96d56Sopenharmony_ci    propagate=1
12967db96d56Sopenharmony_ci    qualname=compiler.parser
12977db96d56Sopenharmony_ci
12987db96d56Sopenharmony_ci    [handler_hand1]
12997db96d56Sopenharmony_ci    class=StreamHandler
13007db96d56Sopenharmony_ci    level=NOTSET
13017db96d56Sopenharmony_ci    formatter=form1
13027db96d56Sopenharmony_ci    args=(sys.stdout,)
13037db96d56Sopenharmony_ci
13047db96d56Sopenharmony_ci    [formatter_form1]
13057db96d56Sopenharmony_ci    format=%(levelname)s ++ %(message)s
13067db96d56Sopenharmony_ci    datefmt=
13077db96d56Sopenharmony_ci    """
13087db96d56Sopenharmony_ci
13097db96d56Sopenharmony_ci    # config2 has a subtle configuration error that should be reported
13107db96d56Sopenharmony_ci    config2 = config1.replace("sys.stdout", "sys.stbout")
13117db96d56Sopenharmony_ci
13127db96d56Sopenharmony_ci    # config3 has a less subtle configuration error
13137db96d56Sopenharmony_ci    config3 = config1.replace("formatter=form1", "formatter=misspelled_name")
13147db96d56Sopenharmony_ci
13157db96d56Sopenharmony_ci    # config4 specifies a custom formatter class to be loaded
13167db96d56Sopenharmony_ci    config4 = """
13177db96d56Sopenharmony_ci    [loggers]
13187db96d56Sopenharmony_ci    keys=root
13197db96d56Sopenharmony_ci
13207db96d56Sopenharmony_ci    [handlers]
13217db96d56Sopenharmony_ci    keys=hand1
13227db96d56Sopenharmony_ci
13237db96d56Sopenharmony_ci    [formatters]
13247db96d56Sopenharmony_ci    keys=form1
13257db96d56Sopenharmony_ci
13267db96d56Sopenharmony_ci    [logger_root]
13277db96d56Sopenharmony_ci    level=NOTSET
13287db96d56Sopenharmony_ci    handlers=hand1
13297db96d56Sopenharmony_ci
13307db96d56Sopenharmony_ci    [handler_hand1]
13317db96d56Sopenharmony_ci    class=StreamHandler
13327db96d56Sopenharmony_ci    level=NOTSET
13337db96d56Sopenharmony_ci    formatter=form1
13347db96d56Sopenharmony_ci    args=(sys.stdout,)
13357db96d56Sopenharmony_ci
13367db96d56Sopenharmony_ci    [formatter_form1]
13377db96d56Sopenharmony_ci    class=""" + __name__ + """.ExceptionFormatter
13387db96d56Sopenharmony_ci    format=%(levelname)s:%(name)s:%(message)s
13397db96d56Sopenharmony_ci    datefmt=
13407db96d56Sopenharmony_ci    """
13417db96d56Sopenharmony_ci
13427db96d56Sopenharmony_ci    # config5 specifies a custom handler class to be loaded
13437db96d56Sopenharmony_ci    config5 = config1.replace('class=StreamHandler', 'class=logging.StreamHandler')
13447db96d56Sopenharmony_ci
13457db96d56Sopenharmony_ci    # config6 uses ', ' delimiters in the handlers and formatters sections
13467db96d56Sopenharmony_ci    config6 = """
13477db96d56Sopenharmony_ci    [loggers]
13487db96d56Sopenharmony_ci    keys=root,parser
13497db96d56Sopenharmony_ci
13507db96d56Sopenharmony_ci    [handlers]
13517db96d56Sopenharmony_ci    keys=hand1, hand2
13527db96d56Sopenharmony_ci
13537db96d56Sopenharmony_ci    [formatters]
13547db96d56Sopenharmony_ci    keys=form1, form2
13557db96d56Sopenharmony_ci
13567db96d56Sopenharmony_ci    [logger_root]
13577db96d56Sopenharmony_ci    level=WARNING
13587db96d56Sopenharmony_ci    handlers=
13597db96d56Sopenharmony_ci
13607db96d56Sopenharmony_ci    [logger_parser]
13617db96d56Sopenharmony_ci    level=DEBUG
13627db96d56Sopenharmony_ci    handlers=hand1
13637db96d56Sopenharmony_ci    propagate=1
13647db96d56Sopenharmony_ci    qualname=compiler.parser
13657db96d56Sopenharmony_ci
13667db96d56Sopenharmony_ci    [handler_hand1]
13677db96d56Sopenharmony_ci    class=StreamHandler
13687db96d56Sopenharmony_ci    level=NOTSET
13697db96d56Sopenharmony_ci    formatter=form1
13707db96d56Sopenharmony_ci    args=(sys.stdout,)
13717db96d56Sopenharmony_ci
13727db96d56Sopenharmony_ci    [handler_hand2]
13737db96d56Sopenharmony_ci    class=StreamHandler
13747db96d56Sopenharmony_ci    level=NOTSET
13757db96d56Sopenharmony_ci    formatter=form1
13767db96d56Sopenharmony_ci    args=(sys.stderr,)
13777db96d56Sopenharmony_ci
13787db96d56Sopenharmony_ci    [formatter_form1]
13797db96d56Sopenharmony_ci    format=%(levelname)s ++ %(message)s
13807db96d56Sopenharmony_ci    datefmt=
13817db96d56Sopenharmony_ci
13827db96d56Sopenharmony_ci    [formatter_form2]
13837db96d56Sopenharmony_ci    format=%(message)s
13847db96d56Sopenharmony_ci    datefmt=
13857db96d56Sopenharmony_ci    """
13867db96d56Sopenharmony_ci
13877db96d56Sopenharmony_ci    # config7 adds a compiler logger, and uses kwargs instead of args.
13887db96d56Sopenharmony_ci    config7 = """
13897db96d56Sopenharmony_ci    [loggers]
13907db96d56Sopenharmony_ci    keys=root,parser,compiler
13917db96d56Sopenharmony_ci
13927db96d56Sopenharmony_ci    [handlers]
13937db96d56Sopenharmony_ci    keys=hand1
13947db96d56Sopenharmony_ci
13957db96d56Sopenharmony_ci    [formatters]
13967db96d56Sopenharmony_ci    keys=form1
13977db96d56Sopenharmony_ci
13987db96d56Sopenharmony_ci    [logger_root]
13997db96d56Sopenharmony_ci    level=WARNING
14007db96d56Sopenharmony_ci    handlers=hand1
14017db96d56Sopenharmony_ci
14027db96d56Sopenharmony_ci    [logger_compiler]
14037db96d56Sopenharmony_ci    level=DEBUG
14047db96d56Sopenharmony_ci    handlers=
14057db96d56Sopenharmony_ci    propagate=1
14067db96d56Sopenharmony_ci    qualname=compiler
14077db96d56Sopenharmony_ci
14087db96d56Sopenharmony_ci    [logger_parser]
14097db96d56Sopenharmony_ci    level=DEBUG
14107db96d56Sopenharmony_ci    handlers=
14117db96d56Sopenharmony_ci    propagate=1
14127db96d56Sopenharmony_ci    qualname=compiler.parser
14137db96d56Sopenharmony_ci
14147db96d56Sopenharmony_ci    [handler_hand1]
14157db96d56Sopenharmony_ci    class=StreamHandler
14167db96d56Sopenharmony_ci    level=NOTSET
14177db96d56Sopenharmony_ci    formatter=form1
14187db96d56Sopenharmony_ci    kwargs={'stream': sys.stdout,}
14197db96d56Sopenharmony_ci
14207db96d56Sopenharmony_ci    [formatter_form1]
14217db96d56Sopenharmony_ci    format=%(levelname)s ++ %(message)s
14227db96d56Sopenharmony_ci    datefmt=
14237db96d56Sopenharmony_ci    """
14247db96d56Sopenharmony_ci
14257db96d56Sopenharmony_ci    # config 8, check for resource warning
14267db96d56Sopenharmony_ci    config8 = r"""
14277db96d56Sopenharmony_ci    [loggers]
14287db96d56Sopenharmony_ci    keys=root
14297db96d56Sopenharmony_ci
14307db96d56Sopenharmony_ci    [handlers]
14317db96d56Sopenharmony_ci    keys=file
14327db96d56Sopenharmony_ci
14337db96d56Sopenharmony_ci    [formatters]
14347db96d56Sopenharmony_ci    keys=
14357db96d56Sopenharmony_ci
14367db96d56Sopenharmony_ci    [logger_root]
14377db96d56Sopenharmony_ci    level=DEBUG
14387db96d56Sopenharmony_ci    handlers=file
14397db96d56Sopenharmony_ci
14407db96d56Sopenharmony_ci    [handler_file]
14417db96d56Sopenharmony_ci    class=FileHandler
14427db96d56Sopenharmony_ci    level=DEBUG
14437db96d56Sopenharmony_ci    args=("{tempfile}",)
14447db96d56Sopenharmony_ci    kwargs={{"encoding": "utf-8"}}
14457db96d56Sopenharmony_ci    """
14467db96d56Sopenharmony_ci
14477db96d56Sopenharmony_ci    disable_test = """
14487db96d56Sopenharmony_ci    [loggers]
14497db96d56Sopenharmony_ci    keys=root
14507db96d56Sopenharmony_ci
14517db96d56Sopenharmony_ci    [handlers]
14527db96d56Sopenharmony_ci    keys=screen
14537db96d56Sopenharmony_ci
14547db96d56Sopenharmony_ci    [formatters]
14557db96d56Sopenharmony_ci    keys=
14567db96d56Sopenharmony_ci
14577db96d56Sopenharmony_ci    [logger_root]
14587db96d56Sopenharmony_ci    level=DEBUG
14597db96d56Sopenharmony_ci    handlers=screen
14607db96d56Sopenharmony_ci
14617db96d56Sopenharmony_ci    [handler_screen]
14627db96d56Sopenharmony_ci    level=DEBUG
14637db96d56Sopenharmony_ci    class=StreamHandler
14647db96d56Sopenharmony_ci    args=(sys.stdout,)
14657db96d56Sopenharmony_ci    formatter=
14667db96d56Sopenharmony_ci    """
14677db96d56Sopenharmony_ci
14687db96d56Sopenharmony_ci    def apply_config(self, conf, **kwargs):
14697db96d56Sopenharmony_ci        file = io.StringIO(textwrap.dedent(conf))
14707db96d56Sopenharmony_ci        logging.config.fileConfig(file, encoding="utf-8", **kwargs)
14717db96d56Sopenharmony_ci
14727db96d56Sopenharmony_ci    def test_config0_ok(self):
14737db96d56Sopenharmony_ci        # A simple config file which overrides the default settings.
14747db96d56Sopenharmony_ci        with support.captured_stdout() as output:
14757db96d56Sopenharmony_ci            self.apply_config(self.config0)
14767db96d56Sopenharmony_ci            logger = logging.getLogger()
14777db96d56Sopenharmony_ci            # Won't output anything
14787db96d56Sopenharmony_ci            logger.info(self.next_message())
14797db96d56Sopenharmony_ci            # Outputs a message
14807db96d56Sopenharmony_ci            logger.error(self.next_message())
14817db96d56Sopenharmony_ci            self.assert_log_lines([
14827db96d56Sopenharmony_ci                ('ERROR', '2'),
14837db96d56Sopenharmony_ci            ], stream=output)
14847db96d56Sopenharmony_ci            # Original logger output is empty.
14857db96d56Sopenharmony_ci            self.assert_log_lines([])
14867db96d56Sopenharmony_ci
14877db96d56Sopenharmony_ci    def test_config0_using_cp_ok(self):
14887db96d56Sopenharmony_ci        # A simple config file which overrides the default settings.
14897db96d56Sopenharmony_ci        with support.captured_stdout() as output:
14907db96d56Sopenharmony_ci            file = io.StringIO(textwrap.dedent(self.config0))
14917db96d56Sopenharmony_ci            cp = configparser.ConfigParser()
14927db96d56Sopenharmony_ci            cp.read_file(file)
14937db96d56Sopenharmony_ci            logging.config.fileConfig(cp)
14947db96d56Sopenharmony_ci            logger = logging.getLogger()
14957db96d56Sopenharmony_ci            # Won't output anything
14967db96d56Sopenharmony_ci            logger.info(self.next_message())
14977db96d56Sopenharmony_ci            # Outputs a message
14987db96d56Sopenharmony_ci            logger.error(self.next_message())
14997db96d56Sopenharmony_ci            self.assert_log_lines([
15007db96d56Sopenharmony_ci                ('ERROR', '2'),
15017db96d56Sopenharmony_ci            ], stream=output)
15027db96d56Sopenharmony_ci            # Original logger output is empty.
15037db96d56Sopenharmony_ci            self.assert_log_lines([])
15047db96d56Sopenharmony_ci
15057db96d56Sopenharmony_ci    def test_config1_ok(self, config=config1):
15067db96d56Sopenharmony_ci        # A config file defining a sub-parser as well.
15077db96d56Sopenharmony_ci        with support.captured_stdout() as output:
15087db96d56Sopenharmony_ci            self.apply_config(config)
15097db96d56Sopenharmony_ci            logger = logging.getLogger("compiler.parser")
15107db96d56Sopenharmony_ci            # Both will output a message
15117db96d56Sopenharmony_ci            logger.info(self.next_message())
15127db96d56Sopenharmony_ci            logger.error(self.next_message())
15137db96d56Sopenharmony_ci            self.assert_log_lines([
15147db96d56Sopenharmony_ci                ('INFO', '1'),
15157db96d56Sopenharmony_ci                ('ERROR', '2'),
15167db96d56Sopenharmony_ci            ], stream=output)
15177db96d56Sopenharmony_ci            # Original logger output is empty.
15187db96d56Sopenharmony_ci            self.assert_log_lines([])
15197db96d56Sopenharmony_ci
15207db96d56Sopenharmony_ci    def test_config2_failure(self):
15217db96d56Sopenharmony_ci        # A simple config file which overrides the default settings.
15227db96d56Sopenharmony_ci        self.assertRaises(Exception, self.apply_config, self.config2)
15237db96d56Sopenharmony_ci
15247db96d56Sopenharmony_ci    def test_config3_failure(self):
15257db96d56Sopenharmony_ci        # A simple config file which overrides the default settings.
15267db96d56Sopenharmony_ci        self.assertRaises(Exception, self.apply_config, self.config3)
15277db96d56Sopenharmony_ci
15287db96d56Sopenharmony_ci    def test_config4_ok(self):
15297db96d56Sopenharmony_ci        # A config file specifying a custom formatter class.
15307db96d56Sopenharmony_ci        with support.captured_stdout() as output:
15317db96d56Sopenharmony_ci            self.apply_config(self.config4)
15327db96d56Sopenharmony_ci            logger = logging.getLogger()
15337db96d56Sopenharmony_ci            try:
15347db96d56Sopenharmony_ci                raise RuntimeError()
15357db96d56Sopenharmony_ci            except RuntimeError:
15367db96d56Sopenharmony_ci                logging.exception("just testing")
15377db96d56Sopenharmony_ci            sys.stdout.seek(0)
15387db96d56Sopenharmony_ci            self.assertEqual(output.getvalue(),
15397db96d56Sopenharmony_ci                "ERROR:root:just testing\nGot a [RuntimeError]\n")
15407db96d56Sopenharmony_ci            # Original logger output is empty
15417db96d56Sopenharmony_ci            self.assert_log_lines([])
15427db96d56Sopenharmony_ci
15437db96d56Sopenharmony_ci    def test_config5_ok(self):
15447db96d56Sopenharmony_ci        self.test_config1_ok(config=self.config5)
15457db96d56Sopenharmony_ci
15467db96d56Sopenharmony_ci    def test_config6_ok(self):
15477db96d56Sopenharmony_ci        self.test_config1_ok(config=self.config6)
15487db96d56Sopenharmony_ci
15497db96d56Sopenharmony_ci    def test_config7_ok(self):
15507db96d56Sopenharmony_ci        with support.captured_stdout() as output:
15517db96d56Sopenharmony_ci            self.apply_config(self.config1a)
15527db96d56Sopenharmony_ci            logger = logging.getLogger("compiler.parser")
15537db96d56Sopenharmony_ci            # See issue #11424. compiler-hyphenated sorts
15547db96d56Sopenharmony_ci            # between compiler and compiler.xyz and this
15557db96d56Sopenharmony_ci            # was preventing compiler.xyz from being included
15567db96d56Sopenharmony_ci            # in the child loggers of compiler because of an
15577db96d56Sopenharmony_ci            # overzealous loop termination condition.
15587db96d56Sopenharmony_ci            hyphenated = logging.getLogger('compiler-hyphenated')
15597db96d56Sopenharmony_ci            # All will output a message
15607db96d56Sopenharmony_ci            logger.info(self.next_message())
15617db96d56Sopenharmony_ci            logger.error(self.next_message())
15627db96d56Sopenharmony_ci            hyphenated.critical(self.next_message())
15637db96d56Sopenharmony_ci            self.assert_log_lines([
15647db96d56Sopenharmony_ci                ('INFO', '1'),
15657db96d56Sopenharmony_ci                ('ERROR', '2'),
15667db96d56Sopenharmony_ci                ('CRITICAL', '3'),
15677db96d56Sopenharmony_ci            ], stream=output)
15687db96d56Sopenharmony_ci            # Original logger output is empty.
15697db96d56Sopenharmony_ci            self.assert_log_lines([])
15707db96d56Sopenharmony_ci        with support.captured_stdout() as output:
15717db96d56Sopenharmony_ci            self.apply_config(self.config7)
15727db96d56Sopenharmony_ci            logger = logging.getLogger("compiler.parser")
15737db96d56Sopenharmony_ci            self.assertFalse(logger.disabled)
15747db96d56Sopenharmony_ci            # Both will output a message
15757db96d56Sopenharmony_ci            logger.info(self.next_message())
15767db96d56Sopenharmony_ci            logger.error(self.next_message())
15777db96d56Sopenharmony_ci            logger = logging.getLogger("compiler.lexer")
15787db96d56Sopenharmony_ci            # Both will output a message
15797db96d56Sopenharmony_ci            logger.info(self.next_message())
15807db96d56Sopenharmony_ci            logger.error(self.next_message())
15817db96d56Sopenharmony_ci            # Will not appear
15827db96d56Sopenharmony_ci            hyphenated.critical(self.next_message())
15837db96d56Sopenharmony_ci            self.assert_log_lines([
15847db96d56Sopenharmony_ci                ('INFO', '4'),
15857db96d56Sopenharmony_ci                ('ERROR', '5'),
15867db96d56Sopenharmony_ci                ('INFO', '6'),
15877db96d56Sopenharmony_ci                ('ERROR', '7'),
15887db96d56Sopenharmony_ci            ], stream=output)
15897db96d56Sopenharmony_ci            # Original logger output is empty.
15907db96d56Sopenharmony_ci            self.assert_log_lines([])
15917db96d56Sopenharmony_ci
15927db96d56Sopenharmony_ci    def test_config8_ok(self):
15937db96d56Sopenharmony_ci
15947db96d56Sopenharmony_ci        def cleanup(h1, fn):
15957db96d56Sopenharmony_ci            h1.close()
15967db96d56Sopenharmony_ci            os.remove(fn)
15977db96d56Sopenharmony_ci
15987db96d56Sopenharmony_ci        with self.check_no_resource_warning():
15997db96d56Sopenharmony_ci            fd, fn = tempfile.mkstemp(".log", "test_logging-X-")
16007db96d56Sopenharmony_ci            os.close(fd)
16017db96d56Sopenharmony_ci
16027db96d56Sopenharmony_ci            # Replace single backslash with double backslash in windows
16037db96d56Sopenharmony_ci            # to avoid unicode error during string formatting
16047db96d56Sopenharmony_ci            if os.name == "nt":
16057db96d56Sopenharmony_ci                fn = fn.replace("\\", "\\\\")
16067db96d56Sopenharmony_ci
16077db96d56Sopenharmony_ci            config8 = self.config8.format(tempfile=fn)
16087db96d56Sopenharmony_ci
16097db96d56Sopenharmony_ci            self.apply_config(config8)
16107db96d56Sopenharmony_ci            self.apply_config(config8)
16117db96d56Sopenharmony_ci
16127db96d56Sopenharmony_ci        handler = logging.root.handlers[0]
16137db96d56Sopenharmony_ci        self.addCleanup(cleanup, handler, fn)
16147db96d56Sopenharmony_ci
16157db96d56Sopenharmony_ci    def test_logger_disabling(self):
16167db96d56Sopenharmony_ci        self.apply_config(self.disable_test)
16177db96d56Sopenharmony_ci        logger = logging.getLogger('some_pristine_logger')
16187db96d56Sopenharmony_ci        self.assertFalse(logger.disabled)
16197db96d56Sopenharmony_ci        self.apply_config(self.disable_test)
16207db96d56Sopenharmony_ci        self.assertTrue(logger.disabled)
16217db96d56Sopenharmony_ci        self.apply_config(self.disable_test, disable_existing_loggers=False)
16227db96d56Sopenharmony_ci        self.assertFalse(logger.disabled)
16237db96d56Sopenharmony_ci
16247db96d56Sopenharmony_ci    def test_config_set_handler_names(self):
16257db96d56Sopenharmony_ci        test_config = """
16267db96d56Sopenharmony_ci            [loggers]
16277db96d56Sopenharmony_ci            keys=root
16287db96d56Sopenharmony_ci
16297db96d56Sopenharmony_ci            [handlers]
16307db96d56Sopenharmony_ci            keys=hand1
16317db96d56Sopenharmony_ci
16327db96d56Sopenharmony_ci            [formatters]
16337db96d56Sopenharmony_ci            keys=form1
16347db96d56Sopenharmony_ci
16357db96d56Sopenharmony_ci            [logger_root]
16367db96d56Sopenharmony_ci            handlers=hand1
16377db96d56Sopenharmony_ci
16387db96d56Sopenharmony_ci            [handler_hand1]
16397db96d56Sopenharmony_ci            class=StreamHandler
16407db96d56Sopenharmony_ci            formatter=form1
16417db96d56Sopenharmony_ci
16427db96d56Sopenharmony_ci            [formatter_form1]
16437db96d56Sopenharmony_ci            format=%(levelname)s ++ %(message)s
16447db96d56Sopenharmony_ci            """
16457db96d56Sopenharmony_ci        self.apply_config(test_config)
16467db96d56Sopenharmony_ci        self.assertEqual(logging.getLogger().handlers[0].name, 'hand1')
16477db96d56Sopenharmony_ci
16487db96d56Sopenharmony_ci    def test_exception_if_confg_file_is_invalid(self):
16497db96d56Sopenharmony_ci        test_config = """
16507db96d56Sopenharmony_ci            [loggers]
16517db96d56Sopenharmony_ci            keys=root
16527db96d56Sopenharmony_ci
16537db96d56Sopenharmony_ci            [handlers]
16547db96d56Sopenharmony_ci            keys=hand1
16557db96d56Sopenharmony_ci
16567db96d56Sopenharmony_ci            [formatters]
16577db96d56Sopenharmony_ci            keys=form1
16587db96d56Sopenharmony_ci
16597db96d56Sopenharmony_ci            [logger_root]
16607db96d56Sopenharmony_ci            handlers=hand1
16617db96d56Sopenharmony_ci
16627db96d56Sopenharmony_ci            [handler_hand1]
16637db96d56Sopenharmony_ci            class=StreamHandler
16647db96d56Sopenharmony_ci            formatter=form1
16657db96d56Sopenharmony_ci
16667db96d56Sopenharmony_ci            [formatter_form1]
16677db96d56Sopenharmony_ci            format=%(levelname)s ++ %(message)s
16687db96d56Sopenharmony_ci
16697db96d56Sopenharmony_ci            prince
16707db96d56Sopenharmony_ci            """
16717db96d56Sopenharmony_ci
16727db96d56Sopenharmony_ci        file = io.StringIO(textwrap.dedent(test_config))
16737db96d56Sopenharmony_ci        self.assertRaises(RuntimeError, logging.config.fileConfig, file)
16747db96d56Sopenharmony_ci
16757db96d56Sopenharmony_ci    def test_exception_if_confg_file_is_empty(self):
16767db96d56Sopenharmony_ci        fd, fn = tempfile.mkstemp(prefix='test_empty_', suffix='.ini')
16777db96d56Sopenharmony_ci        os.close(fd)
16787db96d56Sopenharmony_ci        self.assertRaises(RuntimeError, logging.config.fileConfig, fn)
16797db96d56Sopenharmony_ci        os.remove(fn)
16807db96d56Sopenharmony_ci
16817db96d56Sopenharmony_ci    def test_exception_if_config_file_does_not_exist(self):
16827db96d56Sopenharmony_ci        self.assertRaises(FileNotFoundError, logging.config.fileConfig, 'filenotfound')
16837db96d56Sopenharmony_ci
16847db96d56Sopenharmony_ci    def test_defaults_do_no_interpolation(self):
16857db96d56Sopenharmony_ci        """bpo-33802 defaults should not get interpolated"""
16867db96d56Sopenharmony_ci        ini = textwrap.dedent("""
16877db96d56Sopenharmony_ci            [formatters]
16887db96d56Sopenharmony_ci            keys=default
16897db96d56Sopenharmony_ci
16907db96d56Sopenharmony_ci            [formatter_default]
16917db96d56Sopenharmony_ci
16927db96d56Sopenharmony_ci            [handlers]
16937db96d56Sopenharmony_ci            keys=console
16947db96d56Sopenharmony_ci
16957db96d56Sopenharmony_ci            [handler_console]
16967db96d56Sopenharmony_ci            class=logging.StreamHandler
16977db96d56Sopenharmony_ci            args=tuple()
16987db96d56Sopenharmony_ci
16997db96d56Sopenharmony_ci            [loggers]
17007db96d56Sopenharmony_ci            keys=root
17017db96d56Sopenharmony_ci
17027db96d56Sopenharmony_ci            [logger_root]
17037db96d56Sopenharmony_ci            formatter=default
17047db96d56Sopenharmony_ci            handlers=console
17057db96d56Sopenharmony_ci            """).strip()
17067db96d56Sopenharmony_ci        fd, fn = tempfile.mkstemp(prefix='test_logging_', suffix='.ini')
17077db96d56Sopenharmony_ci        try:
17087db96d56Sopenharmony_ci            os.write(fd, ini.encode('ascii'))
17097db96d56Sopenharmony_ci            os.close(fd)
17107db96d56Sopenharmony_ci            logging.config.fileConfig(
17117db96d56Sopenharmony_ci                fn,
17127db96d56Sopenharmony_ci                encoding="utf-8",
17137db96d56Sopenharmony_ci                defaults=dict(
17147db96d56Sopenharmony_ci                    version=1,
17157db96d56Sopenharmony_ci                    disable_existing_loggers=False,
17167db96d56Sopenharmony_ci                    formatters={
17177db96d56Sopenharmony_ci                        "generic": {
17187db96d56Sopenharmony_ci                            "format": "%(asctime)s [%(process)d] [%(levelname)s] %(message)s",
17197db96d56Sopenharmony_ci                            "datefmt": "[%Y-%m-%d %H:%M:%S %z]",
17207db96d56Sopenharmony_ci                            "class": "logging.Formatter"
17217db96d56Sopenharmony_ci                        },
17227db96d56Sopenharmony_ci                    },
17237db96d56Sopenharmony_ci                )
17247db96d56Sopenharmony_ci            )
17257db96d56Sopenharmony_ci        finally:
17267db96d56Sopenharmony_ci            os.unlink(fn)
17277db96d56Sopenharmony_ci
17287db96d56Sopenharmony_ci
17297db96d56Sopenharmony_ci@support.requires_working_socket()
17307db96d56Sopenharmony_ci@threading_helper.requires_working_threading()
17317db96d56Sopenharmony_ciclass SocketHandlerTest(BaseTest):
17327db96d56Sopenharmony_ci
17337db96d56Sopenharmony_ci    """Test for SocketHandler objects."""
17347db96d56Sopenharmony_ci
17357db96d56Sopenharmony_ci    server_class = TestTCPServer
17367db96d56Sopenharmony_ci    address = ('localhost', 0)
17377db96d56Sopenharmony_ci
17387db96d56Sopenharmony_ci    def setUp(self):
17397db96d56Sopenharmony_ci        """Set up a TCP server to receive log messages, and a SocketHandler
17407db96d56Sopenharmony_ci        pointing to that server's address and port."""
17417db96d56Sopenharmony_ci        BaseTest.setUp(self)
17427db96d56Sopenharmony_ci        # Issue #29177: deal with errors that happen during setup
17437db96d56Sopenharmony_ci        self.server = self.sock_hdlr = self.server_exception = None
17447db96d56Sopenharmony_ci        try:
17457db96d56Sopenharmony_ci            self.server = server = self.server_class(self.address,
17467db96d56Sopenharmony_ci                                                     self.handle_socket, 0.01)
17477db96d56Sopenharmony_ci            server.start()
17487db96d56Sopenharmony_ci            # Uncomment next line to test error recovery in setUp()
17497db96d56Sopenharmony_ci            # raise OSError('dummy error raised')
17507db96d56Sopenharmony_ci        except OSError as e:
17517db96d56Sopenharmony_ci            self.server_exception = e
17527db96d56Sopenharmony_ci            return
17537db96d56Sopenharmony_ci        server.ready.wait()
17547db96d56Sopenharmony_ci        hcls = logging.handlers.SocketHandler
17557db96d56Sopenharmony_ci        if isinstance(server.server_address, tuple):
17567db96d56Sopenharmony_ci            self.sock_hdlr = hcls('localhost', server.port)
17577db96d56Sopenharmony_ci        else:
17587db96d56Sopenharmony_ci            self.sock_hdlr = hcls(server.server_address, None)
17597db96d56Sopenharmony_ci        self.log_output = ''
17607db96d56Sopenharmony_ci        self.root_logger.removeHandler(self.root_logger.handlers[0])
17617db96d56Sopenharmony_ci        self.root_logger.addHandler(self.sock_hdlr)
17627db96d56Sopenharmony_ci        self.handled = threading.Semaphore(0)
17637db96d56Sopenharmony_ci
17647db96d56Sopenharmony_ci    def tearDown(self):
17657db96d56Sopenharmony_ci        """Shutdown the TCP server."""
17667db96d56Sopenharmony_ci        try:
17677db96d56Sopenharmony_ci            if self.sock_hdlr:
17687db96d56Sopenharmony_ci                self.root_logger.removeHandler(self.sock_hdlr)
17697db96d56Sopenharmony_ci                self.sock_hdlr.close()
17707db96d56Sopenharmony_ci            if self.server:
17717db96d56Sopenharmony_ci                self.server.stop()
17727db96d56Sopenharmony_ci        finally:
17737db96d56Sopenharmony_ci            BaseTest.tearDown(self)
17747db96d56Sopenharmony_ci
17757db96d56Sopenharmony_ci    def handle_socket(self, request):
17767db96d56Sopenharmony_ci        conn = request.connection
17777db96d56Sopenharmony_ci        while True:
17787db96d56Sopenharmony_ci            chunk = conn.recv(4)
17797db96d56Sopenharmony_ci            if len(chunk) < 4:
17807db96d56Sopenharmony_ci                break
17817db96d56Sopenharmony_ci            slen = struct.unpack(">L", chunk)[0]
17827db96d56Sopenharmony_ci            chunk = conn.recv(slen)
17837db96d56Sopenharmony_ci            while len(chunk) < slen:
17847db96d56Sopenharmony_ci                chunk = chunk + conn.recv(slen - len(chunk))
17857db96d56Sopenharmony_ci            obj = pickle.loads(chunk)
17867db96d56Sopenharmony_ci            record = logging.makeLogRecord(obj)
17877db96d56Sopenharmony_ci            self.log_output += record.msg + '\n'
17887db96d56Sopenharmony_ci            self.handled.release()
17897db96d56Sopenharmony_ci
17907db96d56Sopenharmony_ci    def test_output(self):
17917db96d56Sopenharmony_ci        # The log message sent to the SocketHandler is properly received.
17927db96d56Sopenharmony_ci        if self.server_exception:
17937db96d56Sopenharmony_ci            self.skipTest(self.server_exception)
17947db96d56Sopenharmony_ci        logger = logging.getLogger("tcp")
17957db96d56Sopenharmony_ci        logger.error("spam")
17967db96d56Sopenharmony_ci        self.handled.acquire()
17977db96d56Sopenharmony_ci        logger.debug("eggs")
17987db96d56Sopenharmony_ci        self.handled.acquire()
17997db96d56Sopenharmony_ci        self.assertEqual(self.log_output, "spam\neggs\n")
18007db96d56Sopenharmony_ci
18017db96d56Sopenharmony_ci    def test_noserver(self):
18027db96d56Sopenharmony_ci        if self.server_exception:
18037db96d56Sopenharmony_ci            self.skipTest(self.server_exception)
18047db96d56Sopenharmony_ci        # Avoid timing-related failures due to SocketHandler's own hard-wired
18057db96d56Sopenharmony_ci        # one-second timeout on socket.create_connection() (issue #16264).
18067db96d56Sopenharmony_ci        self.sock_hdlr.retryStart = 2.5
18077db96d56Sopenharmony_ci        # Kill the server
18087db96d56Sopenharmony_ci        self.server.stop()
18097db96d56Sopenharmony_ci        # The logging call should try to connect, which should fail
18107db96d56Sopenharmony_ci        try:
18117db96d56Sopenharmony_ci            raise RuntimeError('Deliberate mistake')
18127db96d56Sopenharmony_ci        except RuntimeError:
18137db96d56Sopenharmony_ci            self.root_logger.exception('Never sent')
18147db96d56Sopenharmony_ci        self.root_logger.error('Never sent, either')
18157db96d56Sopenharmony_ci        now = time.time()
18167db96d56Sopenharmony_ci        self.assertGreater(self.sock_hdlr.retryTime, now)
18177db96d56Sopenharmony_ci        time.sleep(self.sock_hdlr.retryTime - now + 0.001)
18187db96d56Sopenharmony_ci        self.root_logger.error('Nor this')
18197db96d56Sopenharmony_ci
18207db96d56Sopenharmony_cidef _get_temp_domain_socket():
18217db96d56Sopenharmony_ci    fd, fn = tempfile.mkstemp(prefix='test_logging_', suffix='.sock')
18227db96d56Sopenharmony_ci    os.close(fd)
18237db96d56Sopenharmony_ci    # just need a name - file can't be present, or we'll get an
18247db96d56Sopenharmony_ci    # 'address already in use' error.
18257db96d56Sopenharmony_ci    os.remove(fn)
18267db96d56Sopenharmony_ci    return fn
18277db96d56Sopenharmony_ci
18287db96d56Sopenharmony_ci@unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required")
18297db96d56Sopenharmony_ciclass UnixSocketHandlerTest(SocketHandlerTest):
18307db96d56Sopenharmony_ci
18317db96d56Sopenharmony_ci    """Test for SocketHandler with unix sockets."""
18327db96d56Sopenharmony_ci
18337db96d56Sopenharmony_ci    if hasattr(socket, "AF_UNIX"):
18347db96d56Sopenharmony_ci        server_class = TestUnixStreamServer
18357db96d56Sopenharmony_ci
18367db96d56Sopenharmony_ci    def setUp(self):
18377db96d56Sopenharmony_ci        # override the definition in the base class
18387db96d56Sopenharmony_ci        self.address = _get_temp_domain_socket()
18397db96d56Sopenharmony_ci        SocketHandlerTest.setUp(self)
18407db96d56Sopenharmony_ci
18417db96d56Sopenharmony_ci    def tearDown(self):
18427db96d56Sopenharmony_ci        SocketHandlerTest.tearDown(self)
18437db96d56Sopenharmony_ci        os_helper.unlink(self.address)
18447db96d56Sopenharmony_ci
18457db96d56Sopenharmony_ci@support.requires_working_socket()
18467db96d56Sopenharmony_ci@threading_helper.requires_working_threading()
18477db96d56Sopenharmony_ciclass DatagramHandlerTest(BaseTest):
18487db96d56Sopenharmony_ci
18497db96d56Sopenharmony_ci    """Test for DatagramHandler."""
18507db96d56Sopenharmony_ci
18517db96d56Sopenharmony_ci    server_class = TestUDPServer
18527db96d56Sopenharmony_ci    address = ('localhost', 0)
18537db96d56Sopenharmony_ci
18547db96d56Sopenharmony_ci    def setUp(self):
18557db96d56Sopenharmony_ci        """Set up a UDP server to receive log messages, and a DatagramHandler
18567db96d56Sopenharmony_ci        pointing to that server's address and port."""
18577db96d56Sopenharmony_ci        BaseTest.setUp(self)
18587db96d56Sopenharmony_ci        # Issue #29177: deal with errors that happen during setup
18597db96d56Sopenharmony_ci        self.server = self.sock_hdlr = self.server_exception = None
18607db96d56Sopenharmony_ci        try:
18617db96d56Sopenharmony_ci            self.server = server = self.server_class(self.address,
18627db96d56Sopenharmony_ci                                                     self.handle_datagram, 0.01)
18637db96d56Sopenharmony_ci            server.start()
18647db96d56Sopenharmony_ci            # Uncomment next line to test error recovery in setUp()
18657db96d56Sopenharmony_ci            # raise OSError('dummy error raised')
18667db96d56Sopenharmony_ci        except OSError as e:
18677db96d56Sopenharmony_ci            self.server_exception = e
18687db96d56Sopenharmony_ci            return
18697db96d56Sopenharmony_ci        server.ready.wait()
18707db96d56Sopenharmony_ci        hcls = logging.handlers.DatagramHandler
18717db96d56Sopenharmony_ci        if isinstance(server.server_address, tuple):
18727db96d56Sopenharmony_ci            self.sock_hdlr = hcls('localhost', server.port)
18737db96d56Sopenharmony_ci        else:
18747db96d56Sopenharmony_ci            self.sock_hdlr = hcls(server.server_address, None)
18757db96d56Sopenharmony_ci        self.log_output = ''
18767db96d56Sopenharmony_ci        self.root_logger.removeHandler(self.root_logger.handlers[0])
18777db96d56Sopenharmony_ci        self.root_logger.addHandler(self.sock_hdlr)
18787db96d56Sopenharmony_ci        self.handled = threading.Event()
18797db96d56Sopenharmony_ci
18807db96d56Sopenharmony_ci    def tearDown(self):
18817db96d56Sopenharmony_ci        """Shutdown the UDP server."""
18827db96d56Sopenharmony_ci        try:
18837db96d56Sopenharmony_ci            if self.server:
18847db96d56Sopenharmony_ci                self.server.stop()
18857db96d56Sopenharmony_ci            if self.sock_hdlr:
18867db96d56Sopenharmony_ci                self.root_logger.removeHandler(self.sock_hdlr)
18877db96d56Sopenharmony_ci                self.sock_hdlr.close()
18887db96d56Sopenharmony_ci        finally:
18897db96d56Sopenharmony_ci            BaseTest.tearDown(self)
18907db96d56Sopenharmony_ci
18917db96d56Sopenharmony_ci    def handle_datagram(self, request):
18927db96d56Sopenharmony_ci        slen = struct.pack('>L', 0) # length of prefix
18937db96d56Sopenharmony_ci        packet = request.packet[len(slen):]
18947db96d56Sopenharmony_ci        obj = pickle.loads(packet)
18957db96d56Sopenharmony_ci        record = logging.makeLogRecord(obj)
18967db96d56Sopenharmony_ci        self.log_output += record.msg + '\n'
18977db96d56Sopenharmony_ci        self.handled.set()
18987db96d56Sopenharmony_ci
18997db96d56Sopenharmony_ci    def test_output(self):
19007db96d56Sopenharmony_ci        # The log message sent to the DatagramHandler is properly received.
19017db96d56Sopenharmony_ci        if self.server_exception:
19027db96d56Sopenharmony_ci            self.skipTest(self.server_exception)
19037db96d56Sopenharmony_ci        logger = logging.getLogger("udp")
19047db96d56Sopenharmony_ci        logger.error("spam")
19057db96d56Sopenharmony_ci        self.handled.wait()
19067db96d56Sopenharmony_ci        self.handled.clear()
19077db96d56Sopenharmony_ci        logger.error("eggs")
19087db96d56Sopenharmony_ci        self.handled.wait()
19097db96d56Sopenharmony_ci        self.assertEqual(self.log_output, "spam\neggs\n")
19107db96d56Sopenharmony_ci
19117db96d56Sopenharmony_ci@unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required")
19127db96d56Sopenharmony_ciclass UnixDatagramHandlerTest(DatagramHandlerTest):
19137db96d56Sopenharmony_ci
19147db96d56Sopenharmony_ci    """Test for DatagramHandler using Unix sockets."""
19157db96d56Sopenharmony_ci
19167db96d56Sopenharmony_ci    if hasattr(socket, "AF_UNIX"):
19177db96d56Sopenharmony_ci        server_class = TestUnixDatagramServer
19187db96d56Sopenharmony_ci
19197db96d56Sopenharmony_ci    def setUp(self):
19207db96d56Sopenharmony_ci        # override the definition in the base class
19217db96d56Sopenharmony_ci        self.address = _get_temp_domain_socket()
19227db96d56Sopenharmony_ci        DatagramHandlerTest.setUp(self)
19237db96d56Sopenharmony_ci
19247db96d56Sopenharmony_ci    def tearDown(self):
19257db96d56Sopenharmony_ci        DatagramHandlerTest.tearDown(self)
19267db96d56Sopenharmony_ci        os_helper.unlink(self.address)
19277db96d56Sopenharmony_ci
19287db96d56Sopenharmony_ci@support.requires_working_socket()
19297db96d56Sopenharmony_ci@threading_helper.requires_working_threading()
19307db96d56Sopenharmony_ciclass SysLogHandlerTest(BaseTest):
19317db96d56Sopenharmony_ci
19327db96d56Sopenharmony_ci    """Test for SysLogHandler using UDP."""
19337db96d56Sopenharmony_ci
19347db96d56Sopenharmony_ci    server_class = TestUDPServer
19357db96d56Sopenharmony_ci    address = ('localhost', 0)
19367db96d56Sopenharmony_ci
19377db96d56Sopenharmony_ci    def setUp(self):
19387db96d56Sopenharmony_ci        """Set up a UDP server to receive log messages, and a SysLogHandler
19397db96d56Sopenharmony_ci        pointing to that server's address and port."""
19407db96d56Sopenharmony_ci        BaseTest.setUp(self)
19417db96d56Sopenharmony_ci        # Issue #29177: deal with errors that happen during setup
19427db96d56Sopenharmony_ci        self.server = self.sl_hdlr = self.server_exception = None
19437db96d56Sopenharmony_ci        try:
19447db96d56Sopenharmony_ci            self.server = server = self.server_class(self.address,
19457db96d56Sopenharmony_ci                                                     self.handle_datagram, 0.01)
19467db96d56Sopenharmony_ci            server.start()
19477db96d56Sopenharmony_ci            # Uncomment next line to test error recovery in setUp()
19487db96d56Sopenharmony_ci            # raise OSError('dummy error raised')
19497db96d56Sopenharmony_ci        except OSError as e:
19507db96d56Sopenharmony_ci            self.server_exception = e
19517db96d56Sopenharmony_ci            return
19527db96d56Sopenharmony_ci        server.ready.wait()
19537db96d56Sopenharmony_ci        hcls = logging.handlers.SysLogHandler
19547db96d56Sopenharmony_ci        if isinstance(server.server_address, tuple):
19557db96d56Sopenharmony_ci            self.sl_hdlr = hcls((server.server_address[0], server.port))
19567db96d56Sopenharmony_ci        else:
19577db96d56Sopenharmony_ci            self.sl_hdlr = hcls(server.server_address)
19587db96d56Sopenharmony_ci        self.log_output = b''
19597db96d56Sopenharmony_ci        self.root_logger.removeHandler(self.root_logger.handlers[0])
19607db96d56Sopenharmony_ci        self.root_logger.addHandler(self.sl_hdlr)
19617db96d56Sopenharmony_ci        self.handled = threading.Event()
19627db96d56Sopenharmony_ci
19637db96d56Sopenharmony_ci    def tearDown(self):
19647db96d56Sopenharmony_ci        """Shutdown the server."""
19657db96d56Sopenharmony_ci        try:
19667db96d56Sopenharmony_ci            if self.server:
19677db96d56Sopenharmony_ci                self.server.stop()
19687db96d56Sopenharmony_ci            if self.sl_hdlr:
19697db96d56Sopenharmony_ci                self.root_logger.removeHandler(self.sl_hdlr)
19707db96d56Sopenharmony_ci                self.sl_hdlr.close()
19717db96d56Sopenharmony_ci        finally:
19727db96d56Sopenharmony_ci            BaseTest.tearDown(self)
19737db96d56Sopenharmony_ci
19747db96d56Sopenharmony_ci    def handle_datagram(self, request):
19757db96d56Sopenharmony_ci        self.log_output = request.packet
19767db96d56Sopenharmony_ci        self.handled.set()
19777db96d56Sopenharmony_ci
19787db96d56Sopenharmony_ci    def test_output(self):
19797db96d56Sopenharmony_ci        if self.server_exception:
19807db96d56Sopenharmony_ci            self.skipTest(self.server_exception)
19817db96d56Sopenharmony_ci        # The log message sent to the SysLogHandler is properly received.
19827db96d56Sopenharmony_ci        logger = logging.getLogger("slh")
19837db96d56Sopenharmony_ci        logger.error("sp\xe4m")
19847db96d56Sopenharmony_ci        self.handled.wait()
19857db96d56Sopenharmony_ci        self.assertEqual(self.log_output, b'<11>sp\xc3\xa4m\x00')
19867db96d56Sopenharmony_ci        self.handled.clear()
19877db96d56Sopenharmony_ci        self.sl_hdlr.append_nul = False
19887db96d56Sopenharmony_ci        logger.error("sp\xe4m")
19897db96d56Sopenharmony_ci        self.handled.wait()
19907db96d56Sopenharmony_ci        self.assertEqual(self.log_output, b'<11>sp\xc3\xa4m')
19917db96d56Sopenharmony_ci        self.handled.clear()
19927db96d56Sopenharmony_ci        self.sl_hdlr.ident = "h\xe4m-"
19937db96d56Sopenharmony_ci        logger.error("sp\xe4m")
19947db96d56Sopenharmony_ci        self.handled.wait()
19957db96d56Sopenharmony_ci        self.assertEqual(self.log_output, b'<11>h\xc3\xa4m-sp\xc3\xa4m')
19967db96d56Sopenharmony_ci
19977db96d56Sopenharmony_ci    def test_udp_reconnection(self):
19987db96d56Sopenharmony_ci        logger = logging.getLogger("slh")
19997db96d56Sopenharmony_ci        self.sl_hdlr.close()
20007db96d56Sopenharmony_ci        self.handled.clear()
20017db96d56Sopenharmony_ci        logger.error("sp\xe4m")
20027db96d56Sopenharmony_ci        self.handled.wait(0.1)
20037db96d56Sopenharmony_ci        self.assertEqual(self.log_output, b'<11>sp\xc3\xa4m\x00')
20047db96d56Sopenharmony_ci
20057db96d56Sopenharmony_ci@unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required")
20067db96d56Sopenharmony_ciclass UnixSysLogHandlerTest(SysLogHandlerTest):
20077db96d56Sopenharmony_ci
20087db96d56Sopenharmony_ci    """Test for SysLogHandler with Unix sockets."""
20097db96d56Sopenharmony_ci
20107db96d56Sopenharmony_ci    if hasattr(socket, "AF_UNIX"):
20117db96d56Sopenharmony_ci        server_class = TestUnixDatagramServer
20127db96d56Sopenharmony_ci
20137db96d56Sopenharmony_ci    def setUp(self):
20147db96d56Sopenharmony_ci        # override the definition in the base class
20157db96d56Sopenharmony_ci        self.address = _get_temp_domain_socket()
20167db96d56Sopenharmony_ci        SysLogHandlerTest.setUp(self)
20177db96d56Sopenharmony_ci
20187db96d56Sopenharmony_ci    def tearDown(self):
20197db96d56Sopenharmony_ci        SysLogHandlerTest.tearDown(self)
20207db96d56Sopenharmony_ci        os_helper.unlink(self.address)
20217db96d56Sopenharmony_ci
20227db96d56Sopenharmony_ci@unittest.skipUnless(socket_helper.IPV6_ENABLED,
20237db96d56Sopenharmony_ci                     'IPv6 support required for this test.')
20247db96d56Sopenharmony_ciclass IPv6SysLogHandlerTest(SysLogHandlerTest):
20257db96d56Sopenharmony_ci
20267db96d56Sopenharmony_ci    """Test for SysLogHandler with IPv6 host."""
20277db96d56Sopenharmony_ci
20287db96d56Sopenharmony_ci    server_class = TestUDPServer
20297db96d56Sopenharmony_ci    address = ('::1', 0)
20307db96d56Sopenharmony_ci
20317db96d56Sopenharmony_ci    def setUp(self):
20327db96d56Sopenharmony_ci        self.server_class.address_family = socket.AF_INET6
20337db96d56Sopenharmony_ci        super(IPv6SysLogHandlerTest, self).setUp()
20347db96d56Sopenharmony_ci
20357db96d56Sopenharmony_ci    def tearDown(self):
20367db96d56Sopenharmony_ci        self.server_class.address_family = socket.AF_INET
20377db96d56Sopenharmony_ci        super(IPv6SysLogHandlerTest, self).tearDown()
20387db96d56Sopenharmony_ci
20397db96d56Sopenharmony_ci@support.requires_working_socket()
20407db96d56Sopenharmony_ci@threading_helper.requires_working_threading()
20417db96d56Sopenharmony_ciclass HTTPHandlerTest(BaseTest):
20427db96d56Sopenharmony_ci    """Test for HTTPHandler."""
20437db96d56Sopenharmony_ci
20447db96d56Sopenharmony_ci    def setUp(self):
20457db96d56Sopenharmony_ci        """Set up an HTTP server to receive log messages, and a HTTPHandler
20467db96d56Sopenharmony_ci        pointing to that server's address and port."""
20477db96d56Sopenharmony_ci        BaseTest.setUp(self)
20487db96d56Sopenharmony_ci        self.handled = threading.Event()
20497db96d56Sopenharmony_ci
20507db96d56Sopenharmony_ci    def handle_request(self, request):
20517db96d56Sopenharmony_ci        self.command = request.command
20527db96d56Sopenharmony_ci        self.log_data = urlparse(request.path)
20537db96d56Sopenharmony_ci        if self.command == 'POST':
20547db96d56Sopenharmony_ci            try:
20557db96d56Sopenharmony_ci                rlen = int(request.headers['Content-Length'])
20567db96d56Sopenharmony_ci                self.post_data = request.rfile.read(rlen)
20577db96d56Sopenharmony_ci            except:
20587db96d56Sopenharmony_ci                self.post_data = None
20597db96d56Sopenharmony_ci        request.send_response(200)
20607db96d56Sopenharmony_ci        request.end_headers()
20617db96d56Sopenharmony_ci        self.handled.set()
20627db96d56Sopenharmony_ci
20637db96d56Sopenharmony_ci    def test_output(self):
20647db96d56Sopenharmony_ci        # The log message sent to the HTTPHandler is properly received.
20657db96d56Sopenharmony_ci        logger = logging.getLogger("http")
20667db96d56Sopenharmony_ci        root_logger = self.root_logger
20677db96d56Sopenharmony_ci        root_logger.removeHandler(self.root_logger.handlers[0])
20687db96d56Sopenharmony_ci        for secure in (False, True):
20697db96d56Sopenharmony_ci            addr = ('localhost', 0)
20707db96d56Sopenharmony_ci            if secure:
20717db96d56Sopenharmony_ci                try:
20727db96d56Sopenharmony_ci                    import ssl
20737db96d56Sopenharmony_ci                except ImportError:
20747db96d56Sopenharmony_ci                    sslctx = None
20757db96d56Sopenharmony_ci                else:
20767db96d56Sopenharmony_ci                    here = os.path.dirname(__file__)
20777db96d56Sopenharmony_ci                    localhost_cert = os.path.join(here, "keycert.pem")
20787db96d56Sopenharmony_ci                    sslctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
20797db96d56Sopenharmony_ci                    sslctx.load_cert_chain(localhost_cert)
20807db96d56Sopenharmony_ci
20817db96d56Sopenharmony_ci                    context = ssl.create_default_context(cafile=localhost_cert)
20827db96d56Sopenharmony_ci            else:
20837db96d56Sopenharmony_ci                sslctx = None
20847db96d56Sopenharmony_ci                context = None
20857db96d56Sopenharmony_ci            self.server = server = TestHTTPServer(addr, self.handle_request,
20867db96d56Sopenharmony_ci                                                    0.01, sslctx=sslctx)
20877db96d56Sopenharmony_ci            server.start()
20887db96d56Sopenharmony_ci            server.ready.wait()
20897db96d56Sopenharmony_ci            host = 'localhost:%d' % server.server_port
20907db96d56Sopenharmony_ci            secure_client = secure and sslctx
20917db96d56Sopenharmony_ci            self.h_hdlr = logging.handlers.HTTPHandler(host, '/frob',
20927db96d56Sopenharmony_ci                                                       secure=secure_client,
20937db96d56Sopenharmony_ci                                                       context=context,
20947db96d56Sopenharmony_ci                                                       credentials=('foo', 'bar'))
20957db96d56Sopenharmony_ci            self.log_data = None
20967db96d56Sopenharmony_ci            root_logger.addHandler(self.h_hdlr)
20977db96d56Sopenharmony_ci
20987db96d56Sopenharmony_ci            for method in ('GET', 'POST'):
20997db96d56Sopenharmony_ci                self.h_hdlr.method = method
21007db96d56Sopenharmony_ci                self.handled.clear()
21017db96d56Sopenharmony_ci                msg = "sp\xe4m"
21027db96d56Sopenharmony_ci                logger.error(msg)
21037db96d56Sopenharmony_ci                self.handled.wait()
21047db96d56Sopenharmony_ci                self.assertEqual(self.log_data.path, '/frob')
21057db96d56Sopenharmony_ci                self.assertEqual(self.command, method)
21067db96d56Sopenharmony_ci                if method == 'GET':
21077db96d56Sopenharmony_ci                    d = parse_qs(self.log_data.query)
21087db96d56Sopenharmony_ci                else:
21097db96d56Sopenharmony_ci                    d = parse_qs(self.post_data.decode('utf-8'))
21107db96d56Sopenharmony_ci                self.assertEqual(d['name'], ['http'])
21117db96d56Sopenharmony_ci                self.assertEqual(d['funcName'], ['test_output'])
21127db96d56Sopenharmony_ci                self.assertEqual(d['msg'], [msg])
21137db96d56Sopenharmony_ci
21147db96d56Sopenharmony_ci            self.server.stop()
21157db96d56Sopenharmony_ci            self.root_logger.removeHandler(self.h_hdlr)
21167db96d56Sopenharmony_ci            self.h_hdlr.close()
21177db96d56Sopenharmony_ci
21187db96d56Sopenharmony_ciclass MemoryTest(BaseTest):
21197db96d56Sopenharmony_ci
21207db96d56Sopenharmony_ci    """Test memory persistence of logger objects."""
21217db96d56Sopenharmony_ci
21227db96d56Sopenharmony_ci    def setUp(self):
21237db96d56Sopenharmony_ci        """Create a dict to remember potentially destroyed objects."""
21247db96d56Sopenharmony_ci        BaseTest.setUp(self)
21257db96d56Sopenharmony_ci        self._survivors = {}
21267db96d56Sopenharmony_ci
21277db96d56Sopenharmony_ci    def _watch_for_survival(self, *args):
21287db96d56Sopenharmony_ci        """Watch the given objects for survival, by creating weakrefs to
21297db96d56Sopenharmony_ci        them."""
21307db96d56Sopenharmony_ci        for obj in args:
21317db96d56Sopenharmony_ci            key = id(obj), repr(obj)
21327db96d56Sopenharmony_ci            self._survivors[key] = weakref.ref(obj)
21337db96d56Sopenharmony_ci
21347db96d56Sopenharmony_ci    def _assertTruesurvival(self):
21357db96d56Sopenharmony_ci        """Assert that all objects watched for survival have survived."""
21367db96d56Sopenharmony_ci        # Trigger cycle breaking.
21377db96d56Sopenharmony_ci        gc.collect()
21387db96d56Sopenharmony_ci        dead = []
21397db96d56Sopenharmony_ci        for (id_, repr_), ref in self._survivors.items():
21407db96d56Sopenharmony_ci            if ref() is None:
21417db96d56Sopenharmony_ci                dead.append(repr_)
21427db96d56Sopenharmony_ci        if dead:
21437db96d56Sopenharmony_ci            self.fail("%d objects should have survived "
21447db96d56Sopenharmony_ci                "but have been destroyed: %s" % (len(dead), ", ".join(dead)))
21457db96d56Sopenharmony_ci
21467db96d56Sopenharmony_ci    def test_persistent_loggers(self):
21477db96d56Sopenharmony_ci        # Logger objects are persistent and retain their configuration, even
21487db96d56Sopenharmony_ci        #  if visible references are destroyed.
21497db96d56Sopenharmony_ci        self.root_logger.setLevel(logging.INFO)
21507db96d56Sopenharmony_ci        foo = logging.getLogger("foo")
21517db96d56Sopenharmony_ci        self._watch_for_survival(foo)
21527db96d56Sopenharmony_ci        foo.setLevel(logging.DEBUG)
21537db96d56Sopenharmony_ci        self.root_logger.debug(self.next_message())
21547db96d56Sopenharmony_ci        foo.debug(self.next_message())
21557db96d56Sopenharmony_ci        self.assert_log_lines([
21567db96d56Sopenharmony_ci            ('foo', 'DEBUG', '2'),
21577db96d56Sopenharmony_ci        ])
21587db96d56Sopenharmony_ci        del foo
21597db96d56Sopenharmony_ci        # foo has survived.
21607db96d56Sopenharmony_ci        self._assertTruesurvival()
21617db96d56Sopenharmony_ci        # foo has retained its settings.
21627db96d56Sopenharmony_ci        bar = logging.getLogger("foo")
21637db96d56Sopenharmony_ci        bar.debug(self.next_message())
21647db96d56Sopenharmony_ci        self.assert_log_lines([
21657db96d56Sopenharmony_ci            ('foo', 'DEBUG', '2'),
21667db96d56Sopenharmony_ci            ('foo', 'DEBUG', '3'),
21677db96d56Sopenharmony_ci        ])
21687db96d56Sopenharmony_ci
21697db96d56Sopenharmony_ci
21707db96d56Sopenharmony_ciclass EncodingTest(BaseTest):
21717db96d56Sopenharmony_ci    def test_encoding_plain_file(self):
21727db96d56Sopenharmony_ci        # In Python 2.x, a plain file object is treated as having no encoding.
21737db96d56Sopenharmony_ci        log = logging.getLogger("test")
21747db96d56Sopenharmony_ci        fd, fn = tempfile.mkstemp(".log", "test_logging-1-")
21757db96d56Sopenharmony_ci        os.close(fd)
21767db96d56Sopenharmony_ci        # the non-ascii data we write to the log.
21777db96d56Sopenharmony_ci        data = "foo\x80"
21787db96d56Sopenharmony_ci        try:
21797db96d56Sopenharmony_ci            handler = logging.FileHandler(fn, encoding="utf-8")
21807db96d56Sopenharmony_ci            log.addHandler(handler)
21817db96d56Sopenharmony_ci            try:
21827db96d56Sopenharmony_ci                # write non-ascii data to the log.
21837db96d56Sopenharmony_ci                log.warning(data)
21847db96d56Sopenharmony_ci            finally:
21857db96d56Sopenharmony_ci                log.removeHandler(handler)
21867db96d56Sopenharmony_ci                handler.close()
21877db96d56Sopenharmony_ci            # check we wrote exactly those bytes, ignoring trailing \n etc
21887db96d56Sopenharmony_ci            f = open(fn, encoding="utf-8")
21897db96d56Sopenharmony_ci            try:
21907db96d56Sopenharmony_ci                self.assertEqual(f.read().rstrip(), data)
21917db96d56Sopenharmony_ci            finally:
21927db96d56Sopenharmony_ci                f.close()
21937db96d56Sopenharmony_ci        finally:
21947db96d56Sopenharmony_ci            if os.path.isfile(fn):
21957db96d56Sopenharmony_ci                os.remove(fn)
21967db96d56Sopenharmony_ci
21977db96d56Sopenharmony_ci    def test_encoding_cyrillic_unicode(self):
21987db96d56Sopenharmony_ci        log = logging.getLogger("test")
21997db96d56Sopenharmony_ci        # Get a message in Unicode: Do svidanya in Cyrillic (meaning goodbye)
22007db96d56Sopenharmony_ci        message = '\u0434\u043e \u0441\u0432\u0438\u0434\u0430\u043d\u0438\u044f'
22017db96d56Sopenharmony_ci        # Ensure it's written in a Cyrillic encoding
22027db96d56Sopenharmony_ci        writer_class = codecs.getwriter('cp1251')
22037db96d56Sopenharmony_ci        writer_class.encoding = 'cp1251'
22047db96d56Sopenharmony_ci        stream = io.BytesIO()
22057db96d56Sopenharmony_ci        writer = writer_class(stream, 'strict')
22067db96d56Sopenharmony_ci        handler = logging.StreamHandler(writer)
22077db96d56Sopenharmony_ci        log.addHandler(handler)
22087db96d56Sopenharmony_ci        try:
22097db96d56Sopenharmony_ci            log.warning(message)
22107db96d56Sopenharmony_ci        finally:
22117db96d56Sopenharmony_ci            log.removeHandler(handler)
22127db96d56Sopenharmony_ci            handler.close()
22137db96d56Sopenharmony_ci        # check we wrote exactly those bytes, ignoring trailing \n etc
22147db96d56Sopenharmony_ci        s = stream.getvalue()
22157db96d56Sopenharmony_ci        # Compare against what the data should be when encoded in CP-1251
22167db96d56Sopenharmony_ci        self.assertEqual(s, b'\xe4\xee \xf1\xe2\xe8\xe4\xe0\xed\xe8\xff\n')
22177db96d56Sopenharmony_ci
22187db96d56Sopenharmony_ci
22197db96d56Sopenharmony_ciclass WarningsTest(BaseTest):
22207db96d56Sopenharmony_ci
22217db96d56Sopenharmony_ci    def test_warnings(self):
22227db96d56Sopenharmony_ci        with warnings.catch_warnings():
22237db96d56Sopenharmony_ci            logging.captureWarnings(True)
22247db96d56Sopenharmony_ci            self.addCleanup(logging.captureWarnings, False)
22257db96d56Sopenharmony_ci            warnings.filterwarnings("always", category=UserWarning)
22267db96d56Sopenharmony_ci            stream = io.StringIO()
22277db96d56Sopenharmony_ci            h = logging.StreamHandler(stream)
22287db96d56Sopenharmony_ci            logger = logging.getLogger("py.warnings")
22297db96d56Sopenharmony_ci            logger.addHandler(h)
22307db96d56Sopenharmony_ci            warnings.warn("I'm warning you...")
22317db96d56Sopenharmony_ci            logger.removeHandler(h)
22327db96d56Sopenharmony_ci            s = stream.getvalue()
22337db96d56Sopenharmony_ci            h.close()
22347db96d56Sopenharmony_ci            self.assertGreater(s.find("UserWarning: I'm warning you...\n"), 0)
22357db96d56Sopenharmony_ci
22367db96d56Sopenharmony_ci            # See if an explicit file uses the original implementation
22377db96d56Sopenharmony_ci            a_file = io.StringIO()
22387db96d56Sopenharmony_ci            warnings.showwarning("Explicit", UserWarning, "dummy.py", 42,
22397db96d56Sopenharmony_ci                                 a_file, "Dummy line")
22407db96d56Sopenharmony_ci            s = a_file.getvalue()
22417db96d56Sopenharmony_ci            a_file.close()
22427db96d56Sopenharmony_ci            self.assertEqual(s,
22437db96d56Sopenharmony_ci                "dummy.py:42: UserWarning: Explicit\n  Dummy line\n")
22447db96d56Sopenharmony_ci
22457db96d56Sopenharmony_ci    def test_warnings_no_handlers(self):
22467db96d56Sopenharmony_ci        with warnings.catch_warnings():
22477db96d56Sopenharmony_ci            logging.captureWarnings(True)
22487db96d56Sopenharmony_ci            self.addCleanup(logging.captureWarnings, False)
22497db96d56Sopenharmony_ci
22507db96d56Sopenharmony_ci            # confirm our assumption: no loggers are set
22517db96d56Sopenharmony_ci            logger = logging.getLogger("py.warnings")
22527db96d56Sopenharmony_ci            self.assertEqual(logger.handlers, [])
22537db96d56Sopenharmony_ci
22547db96d56Sopenharmony_ci            warnings.showwarning("Explicit", UserWarning, "dummy.py", 42)
22557db96d56Sopenharmony_ci            self.assertEqual(len(logger.handlers), 1)
22567db96d56Sopenharmony_ci            self.assertIsInstance(logger.handlers[0], logging.NullHandler)
22577db96d56Sopenharmony_ci
22587db96d56Sopenharmony_ci
22597db96d56Sopenharmony_cidef formatFunc(format, datefmt=None):
22607db96d56Sopenharmony_ci    return logging.Formatter(format, datefmt)
22617db96d56Sopenharmony_ci
22627db96d56Sopenharmony_ciclass myCustomFormatter:
22637db96d56Sopenharmony_ci    def __init__(self, fmt, datefmt=None):
22647db96d56Sopenharmony_ci        pass
22657db96d56Sopenharmony_ci
22667db96d56Sopenharmony_cidef handlerFunc():
22677db96d56Sopenharmony_ci    return logging.StreamHandler()
22687db96d56Sopenharmony_ci
22697db96d56Sopenharmony_ciclass CustomHandler(logging.StreamHandler):
22707db96d56Sopenharmony_ci    pass
22717db96d56Sopenharmony_ci
22727db96d56Sopenharmony_ciclass ConfigDictTest(BaseTest):
22737db96d56Sopenharmony_ci
22747db96d56Sopenharmony_ci    """Reading logging config from a dictionary."""
22757db96d56Sopenharmony_ci
22767db96d56Sopenharmony_ci    check_no_resource_warning = warnings_helper.check_no_resource_warning
22777db96d56Sopenharmony_ci    expected_log_pat = r"^(\w+) \+\+ (\w+)$"
22787db96d56Sopenharmony_ci
22797db96d56Sopenharmony_ci    # config0 is a standard configuration.
22807db96d56Sopenharmony_ci    config0 = {
22817db96d56Sopenharmony_ci        'version': 1,
22827db96d56Sopenharmony_ci        'formatters': {
22837db96d56Sopenharmony_ci            'form1' : {
22847db96d56Sopenharmony_ci                'format' : '%(levelname)s ++ %(message)s',
22857db96d56Sopenharmony_ci            },
22867db96d56Sopenharmony_ci        },
22877db96d56Sopenharmony_ci        'handlers' : {
22887db96d56Sopenharmony_ci            'hand1' : {
22897db96d56Sopenharmony_ci                'class' : 'logging.StreamHandler',
22907db96d56Sopenharmony_ci                'formatter' : 'form1',
22917db96d56Sopenharmony_ci                'level' : 'NOTSET',
22927db96d56Sopenharmony_ci                'stream'  : 'ext://sys.stdout',
22937db96d56Sopenharmony_ci            },
22947db96d56Sopenharmony_ci        },
22957db96d56Sopenharmony_ci        'root' : {
22967db96d56Sopenharmony_ci            'level' : 'WARNING',
22977db96d56Sopenharmony_ci            'handlers' : ['hand1'],
22987db96d56Sopenharmony_ci        },
22997db96d56Sopenharmony_ci    }
23007db96d56Sopenharmony_ci
23017db96d56Sopenharmony_ci    # config1 adds a little to the standard configuration.
23027db96d56Sopenharmony_ci    config1 = {
23037db96d56Sopenharmony_ci        'version': 1,
23047db96d56Sopenharmony_ci        'formatters': {
23057db96d56Sopenharmony_ci            'form1' : {
23067db96d56Sopenharmony_ci                'format' : '%(levelname)s ++ %(message)s',
23077db96d56Sopenharmony_ci            },
23087db96d56Sopenharmony_ci        },
23097db96d56Sopenharmony_ci        'handlers' : {
23107db96d56Sopenharmony_ci            'hand1' : {
23117db96d56Sopenharmony_ci                'class' : 'logging.StreamHandler',
23127db96d56Sopenharmony_ci                'formatter' : 'form1',
23137db96d56Sopenharmony_ci                'level' : 'NOTSET',
23147db96d56Sopenharmony_ci                'stream'  : 'ext://sys.stdout',
23157db96d56Sopenharmony_ci            },
23167db96d56Sopenharmony_ci        },
23177db96d56Sopenharmony_ci        'loggers' : {
23187db96d56Sopenharmony_ci            'compiler.parser' : {
23197db96d56Sopenharmony_ci                'level' : 'DEBUG',
23207db96d56Sopenharmony_ci                'handlers' : ['hand1'],
23217db96d56Sopenharmony_ci            },
23227db96d56Sopenharmony_ci        },
23237db96d56Sopenharmony_ci        'root' : {
23247db96d56Sopenharmony_ci            'level' : 'WARNING',
23257db96d56Sopenharmony_ci        },
23267db96d56Sopenharmony_ci    }
23277db96d56Sopenharmony_ci
23287db96d56Sopenharmony_ci    # config1a moves the handler to the root. Used with config8a
23297db96d56Sopenharmony_ci    config1a = {
23307db96d56Sopenharmony_ci        'version': 1,
23317db96d56Sopenharmony_ci        'formatters': {
23327db96d56Sopenharmony_ci            'form1' : {
23337db96d56Sopenharmony_ci                'format' : '%(levelname)s ++ %(message)s',
23347db96d56Sopenharmony_ci            },
23357db96d56Sopenharmony_ci        },
23367db96d56Sopenharmony_ci        'handlers' : {
23377db96d56Sopenharmony_ci            'hand1' : {
23387db96d56Sopenharmony_ci                'class' : 'logging.StreamHandler',
23397db96d56Sopenharmony_ci                'formatter' : 'form1',
23407db96d56Sopenharmony_ci                'level' : 'NOTSET',
23417db96d56Sopenharmony_ci                'stream'  : 'ext://sys.stdout',
23427db96d56Sopenharmony_ci            },
23437db96d56Sopenharmony_ci        },
23447db96d56Sopenharmony_ci        'loggers' : {
23457db96d56Sopenharmony_ci            'compiler.parser' : {
23467db96d56Sopenharmony_ci                'level' : 'DEBUG',
23477db96d56Sopenharmony_ci            },
23487db96d56Sopenharmony_ci        },
23497db96d56Sopenharmony_ci        'root' : {
23507db96d56Sopenharmony_ci            'level' : 'WARNING',
23517db96d56Sopenharmony_ci            'handlers' : ['hand1'],
23527db96d56Sopenharmony_ci        },
23537db96d56Sopenharmony_ci    }
23547db96d56Sopenharmony_ci
23557db96d56Sopenharmony_ci    # config2 has a subtle configuration error that should be reported
23567db96d56Sopenharmony_ci    config2 = {
23577db96d56Sopenharmony_ci        'version': 1,
23587db96d56Sopenharmony_ci        'formatters': {
23597db96d56Sopenharmony_ci            'form1' : {
23607db96d56Sopenharmony_ci                'format' : '%(levelname)s ++ %(message)s',
23617db96d56Sopenharmony_ci            },
23627db96d56Sopenharmony_ci        },
23637db96d56Sopenharmony_ci        'handlers' : {
23647db96d56Sopenharmony_ci            'hand1' : {
23657db96d56Sopenharmony_ci                'class' : 'logging.StreamHandler',
23667db96d56Sopenharmony_ci                'formatter' : 'form1',
23677db96d56Sopenharmony_ci                'level' : 'NOTSET',
23687db96d56Sopenharmony_ci                'stream'  : 'ext://sys.stdbout',
23697db96d56Sopenharmony_ci            },
23707db96d56Sopenharmony_ci        },
23717db96d56Sopenharmony_ci        'loggers' : {
23727db96d56Sopenharmony_ci            'compiler.parser' : {
23737db96d56Sopenharmony_ci                'level' : 'DEBUG',
23747db96d56Sopenharmony_ci                'handlers' : ['hand1'],
23757db96d56Sopenharmony_ci            },
23767db96d56Sopenharmony_ci        },
23777db96d56Sopenharmony_ci        'root' : {
23787db96d56Sopenharmony_ci            'level' : 'WARNING',
23797db96d56Sopenharmony_ci        },
23807db96d56Sopenharmony_ci    }
23817db96d56Sopenharmony_ci
23827db96d56Sopenharmony_ci    # As config1 but with a misspelt level on a handler
23837db96d56Sopenharmony_ci    config2a = {
23847db96d56Sopenharmony_ci        'version': 1,
23857db96d56Sopenharmony_ci        'formatters': {
23867db96d56Sopenharmony_ci            'form1' : {
23877db96d56Sopenharmony_ci                'format' : '%(levelname)s ++ %(message)s',
23887db96d56Sopenharmony_ci            },
23897db96d56Sopenharmony_ci        },
23907db96d56Sopenharmony_ci        'handlers' : {
23917db96d56Sopenharmony_ci            'hand1' : {
23927db96d56Sopenharmony_ci                'class' : 'logging.StreamHandler',
23937db96d56Sopenharmony_ci                'formatter' : 'form1',
23947db96d56Sopenharmony_ci                'level' : 'NTOSET',
23957db96d56Sopenharmony_ci                'stream'  : 'ext://sys.stdout',
23967db96d56Sopenharmony_ci            },
23977db96d56Sopenharmony_ci        },
23987db96d56Sopenharmony_ci        'loggers' : {
23997db96d56Sopenharmony_ci            'compiler.parser' : {
24007db96d56Sopenharmony_ci                'level' : 'DEBUG',
24017db96d56Sopenharmony_ci                'handlers' : ['hand1'],
24027db96d56Sopenharmony_ci            },
24037db96d56Sopenharmony_ci        },
24047db96d56Sopenharmony_ci        'root' : {
24057db96d56Sopenharmony_ci            'level' : 'WARNING',
24067db96d56Sopenharmony_ci        },
24077db96d56Sopenharmony_ci    }
24087db96d56Sopenharmony_ci
24097db96d56Sopenharmony_ci
24107db96d56Sopenharmony_ci    # As config1 but with a misspelt level on a logger
24117db96d56Sopenharmony_ci    config2b = {
24127db96d56Sopenharmony_ci        'version': 1,
24137db96d56Sopenharmony_ci        'formatters': {
24147db96d56Sopenharmony_ci            'form1' : {
24157db96d56Sopenharmony_ci                'format' : '%(levelname)s ++ %(message)s',
24167db96d56Sopenharmony_ci            },
24177db96d56Sopenharmony_ci        },
24187db96d56Sopenharmony_ci        'handlers' : {
24197db96d56Sopenharmony_ci            'hand1' : {
24207db96d56Sopenharmony_ci                'class' : 'logging.StreamHandler',
24217db96d56Sopenharmony_ci                'formatter' : 'form1',
24227db96d56Sopenharmony_ci                'level' : 'NOTSET',
24237db96d56Sopenharmony_ci                'stream'  : 'ext://sys.stdout',
24247db96d56Sopenharmony_ci            },
24257db96d56Sopenharmony_ci        },
24267db96d56Sopenharmony_ci        'loggers' : {
24277db96d56Sopenharmony_ci            'compiler.parser' : {
24287db96d56Sopenharmony_ci                'level' : 'DEBUG',
24297db96d56Sopenharmony_ci                'handlers' : ['hand1'],
24307db96d56Sopenharmony_ci            },
24317db96d56Sopenharmony_ci        },
24327db96d56Sopenharmony_ci        'root' : {
24337db96d56Sopenharmony_ci            'level' : 'WRANING',
24347db96d56Sopenharmony_ci        },
24357db96d56Sopenharmony_ci    }
24367db96d56Sopenharmony_ci
24377db96d56Sopenharmony_ci    # config3 has a less subtle configuration error
24387db96d56Sopenharmony_ci    config3 = {
24397db96d56Sopenharmony_ci        'version': 1,
24407db96d56Sopenharmony_ci        'formatters': {
24417db96d56Sopenharmony_ci            'form1' : {
24427db96d56Sopenharmony_ci                'format' : '%(levelname)s ++ %(message)s',
24437db96d56Sopenharmony_ci            },
24447db96d56Sopenharmony_ci        },
24457db96d56Sopenharmony_ci        'handlers' : {
24467db96d56Sopenharmony_ci            'hand1' : {
24477db96d56Sopenharmony_ci                'class' : 'logging.StreamHandler',
24487db96d56Sopenharmony_ci                'formatter' : 'misspelled_name',
24497db96d56Sopenharmony_ci                'level' : 'NOTSET',
24507db96d56Sopenharmony_ci                'stream'  : 'ext://sys.stdout',
24517db96d56Sopenharmony_ci            },
24527db96d56Sopenharmony_ci        },
24537db96d56Sopenharmony_ci        'loggers' : {
24547db96d56Sopenharmony_ci            'compiler.parser' : {
24557db96d56Sopenharmony_ci                'level' : 'DEBUG',
24567db96d56Sopenharmony_ci                'handlers' : ['hand1'],
24577db96d56Sopenharmony_ci            },
24587db96d56Sopenharmony_ci        },
24597db96d56Sopenharmony_ci        'root' : {
24607db96d56Sopenharmony_ci            'level' : 'WARNING',
24617db96d56Sopenharmony_ci        },
24627db96d56Sopenharmony_ci    }
24637db96d56Sopenharmony_ci
24647db96d56Sopenharmony_ci    # config4 specifies a custom formatter class to be loaded
24657db96d56Sopenharmony_ci    config4 = {
24667db96d56Sopenharmony_ci        'version': 1,
24677db96d56Sopenharmony_ci        'formatters': {
24687db96d56Sopenharmony_ci            'form1' : {
24697db96d56Sopenharmony_ci                '()' : __name__ + '.ExceptionFormatter',
24707db96d56Sopenharmony_ci                'format' : '%(levelname)s:%(name)s:%(message)s',
24717db96d56Sopenharmony_ci            },
24727db96d56Sopenharmony_ci        },
24737db96d56Sopenharmony_ci        'handlers' : {
24747db96d56Sopenharmony_ci            'hand1' : {
24757db96d56Sopenharmony_ci                'class' : 'logging.StreamHandler',
24767db96d56Sopenharmony_ci                'formatter' : 'form1',
24777db96d56Sopenharmony_ci                'level' : 'NOTSET',
24787db96d56Sopenharmony_ci                'stream'  : 'ext://sys.stdout',
24797db96d56Sopenharmony_ci            },
24807db96d56Sopenharmony_ci        },
24817db96d56Sopenharmony_ci        'root' : {
24827db96d56Sopenharmony_ci            'level' : 'NOTSET',
24837db96d56Sopenharmony_ci                'handlers' : ['hand1'],
24847db96d56Sopenharmony_ci        },
24857db96d56Sopenharmony_ci    }
24867db96d56Sopenharmony_ci
24877db96d56Sopenharmony_ci    # As config4 but using an actual callable rather than a string
24887db96d56Sopenharmony_ci    config4a = {
24897db96d56Sopenharmony_ci        'version': 1,
24907db96d56Sopenharmony_ci        'formatters': {
24917db96d56Sopenharmony_ci            'form1' : {
24927db96d56Sopenharmony_ci                '()' : ExceptionFormatter,
24937db96d56Sopenharmony_ci                'format' : '%(levelname)s:%(name)s:%(message)s',
24947db96d56Sopenharmony_ci            },
24957db96d56Sopenharmony_ci            'form2' : {
24967db96d56Sopenharmony_ci                '()' : __name__ + '.formatFunc',
24977db96d56Sopenharmony_ci                'format' : '%(levelname)s:%(name)s:%(message)s',
24987db96d56Sopenharmony_ci            },
24997db96d56Sopenharmony_ci            'form3' : {
25007db96d56Sopenharmony_ci                '()' : formatFunc,
25017db96d56Sopenharmony_ci                'format' : '%(levelname)s:%(name)s:%(message)s',
25027db96d56Sopenharmony_ci            },
25037db96d56Sopenharmony_ci        },
25047db96d56Sopenharmony_ci        'handlers' : {
25057db96d56Sopenharmony_ci            'hand1' : {
25067db96d56Sopenharmony_ci                'class' : 'logging.StreamHandler',
25077db96d56Sopenharmony_ci                'formatter' : 'form1',
25087db96d56Sopenharmony_ci                'level' : 'NOTSET',
25097db96d56Sopenharmony_ci                'stream'  : 'ext://sys.stdout',
25107db96d56Sopenharmony_ci            },
25117db96d56Sopenharmony_ci            'hand2' : {
25127db96d56Sopenharmony_ci                '()' : handlerFunc,
25137db96d56Sopenharmony_ci            },
25147db96d56Sopenharmony_ci        },
25157db96d56Sopenharmony_ci        'root' : {
25167db96d56Sopenharmony_ci            'level' : 'NOTSET',
25177db96d56Sopenharmony_ci                'handlers' : ['hand1'],
25187db96d56Sopenharmony_ci        },
25197db96d56Sopenharmony_ci    }
25207db96d56Sopenharmony_ci
25217db96d56Sopenharmony_ci    # config5 specifies a custom handler class to be loaded
25227db96d56Sopenharmony_ci    config5 = {
25237db96d56Sopenharmony_ci        'version': 1,
25247db96d56Sopenharmony_ci        'formatters': {
25257db96d56Sopenharmony_ci            'form1' : {
25267db96d56Sopenharmony_ci                'format' : '%(levelname)s ++ %(message)s',
25277db96d56Sopenharmony_ci            },
25287db96d56Sopenharmony_ci        },
25297db96d56Sopenharmony_ci        'handlers' : {
25307db96d56Sopenharmony_ci            'hand1' : {
25317db96d56Sopenharmony_ci                'class' : __name__ + '.CustomHandler',
25327db96d56Sopenharmony_ci                'formatter' : 'form1',
25337db96d56Sopenharmony_ci                'level' : 'NOTSET',
25347db96d56Sopenharmony_ci                'stream'  : 'ext://sys.stdout',
25357db96d56Sopenharmony_ci            },
25367db96d56Sopenharmony_ci        },
25377db96d56Sopenharmony_ci        'loggers' : {
25387db96d56Sopenharmony_ci            'compiler.parser' : {
25397db96d56Sopenharmony_ci                'level' : 'DEBUG',
25407db96d56Sopenharmony_ci                'handlers' : ['hand1'],
25417db96d56Sopenharmony_ci            },
25427db96d56Sopenharmony_ci        },
25437db96d56Sopenharmony_ci        'root' : {
25447db96d56Sopenharmony_ci            'level' : 'WARNING',
25457db96d56Sopenharmony_ci        },
25467db96d56Sopenharmony_ci    }
25477db96d56Sopenharmony_ci
25487db96d56Sopenharmony_ci    # config6 specifies a custom handler class to be loaded
25497db96d56Sopenharmony_ci    # but has bad arguments
25507db96d56Sopenharmony_ci    config6 = {
25517db96d56Sopenharmony_ci        'version': 1,
25527db96d56Sopenharmony_ci        'formatters': {
25537db96d56Sopenharmony_ci            'form1' : {
25547db96d56Sopenharmony_ci                'format' : '%(levelname)s ++ %(message)s',
25557db96d56Sopenharmony_ci            },
25567db96d56Sopenharmony_ci        },
25577db96d56Sopenharmony_ci        'handlers' : {
25587db96d56Sopenharmony_ci            'hand1' : {
25597db96d56Sopenharmony_ci                'class' : __name__ + '.CustomHandler',
25607db96d56Sopenharmony_ci                'formatter' : 'form1',
25617db96d56Sopenharmony_ci                'level' : 'NOTSET',
25627db96d56Sopenharmony_ci                'stream'  : 'ext://sys.stdout',
25637db96d56Sopenharmony_ci                '9' : 'invalid parameter name',
25647db96d56Sopenharmony_ci            },
25657db96d56Sopenharmony_ci        },
25667db96d56Sopenharmony_ci        'loggers' : {
25677db96d56Sopenharmony_ci            'compiler.parser' : {
25687db96d56Sopenharmony_ci                'level' : 'DEBUG',
25697db96d56Sopenharmony_ci                'handlers' : ['hand1'],
25707db96d56Sopenharmony_ci            },
25717db96d56Sopenharmony_ci        },
25727db96d56Sopenharmony_ci        'root' : {
25737db96d56Sopenharmony_ci            'level' : 'WARNING',
25747db96d56Sopenharmony_ci        },
25757db96d56Sopenharmony_ci    }
25767db96d56Sopenharmony_ci
25777db96d56Sopenharmony_ci    # config 7 does not define compiler.parser but defines compiler.lexer
25787db96d56Sopenharmony_ci    # so compiler.parser should be disabled after applying it
25797db96d56Sopenharmony_ci    config7 = {
25807db96d56Sopenharmony_ci        'version': 1,
25817db96d56Sopenharmony_ci        'formatters': {
25827db96d56Sopenharmony_ci            'form1' : {
25837db96d56Sopenharmony_ci                'format' : '%(levelname)s ++ %(message)s',
25847db96d56Sopenharmony_ci            },
25857db96d56Sopenharmony_ci        },
25867db96d56Sopenharmony_ci        'handlers' : {
25877db96d56Sopenharmony_ci            'hand1' : {
25887db96d56Sopenharmony_ci                'class' : 'logging.StreamHandler',
25897db96d56Sopenharmony_ci                'formatter' : 'form1',
25907db96d56Sopenharmony_ci                'level' : 'NOTSET',
25917db96d56Sopenharmony_ci                'stream'  : 'ext://sys.stdout',
25927db96d56Sopenharmony_ci            },
25937db96d56Sopenharmony_ci        },
25947db96d56Sopenharmony_ci        'loggers' : {
25957db96d56Sopenharmony_ci            'compiler.lexer' : {
25967db96d56Sopenharmony_ci                'level' : 'DEBUG',
25977db96d56Sopenharmony_ci                'handlers' : ['hand1'],
25987db96d56Sopenharmony_ci            },
25997db96d56Sopenharmony_ci        },
26007db96d56Sopenharmony_ci        'root' : {
26017db96d56Sopenharmony_ci            'level' : 'WARNING',
26027db96d56Sopenharmony_ci        },
26037db96d56Sopenharmony_ci    }
26047db96d56Sopenharmony_ci
26057db96d56Sopenharmony_ci    # config8 defines both compiler and compiler.lexer
26067db96d56Sopenharmony_ci    # so compiler.parser should not be disabled (since
26077db96d56Sopenharmony_ci    # compiler is defined)
26087db96d56Sopenharmony_ci    config8 = {
26097db96d56Sopenharmony_ci        'version': 1,
26107db96d56Sopenharmony_ci        'disable_existing_loggers' : False,
26117db96d56Sopenharmony_ci        'formatters': {
26127db96d56Sopenharmony_ci            'form1' : {
26137db96d56Sopenharmony_ci                'format' : '%(levelname)s ++ %(message)s',
26147db96d56Sopenharmony_ci            },
26157db96d56Sopenharmony_ci        },
26167db96d56Sopenharmony_ci        'handlers' : {
26177db96d56Sopenharmony_ci            'hand1' : {
26187db96d56Sopenharmony_ci                'class' : 'logging.StreamHandler',
26197db96d56Sopenharmony_ci                'formatter' : 'form1',
26207db96d56Sopenharmony_ci                'level' : 'NOTSET',
26217db96d56Sopenharmony_ci                'stream'  : 'ext://sys.stdout',
26227db96d56Sopenharmony_ci            },
26237db96d56Sopenharmony_ci        },
26247db96d56Sopenharmony_ci        'loggers' : {
26257db96d56Sopenharmony_ci            'compiler' : {
26267db96d56Sopenharmony_ci                'level' : 'DEBUG',
26277db96d56Sopenharmony_ci                'handlers' : ['hand1'],
26287db96d56Sopenharmony_ci            },
26297db96d56Sopenharmony_ci            'compiler.lexer' : {
26307db96d56Sopenharmony_ci            },
26317db96d56Sopenharmony_ci        },
26327db96d56Sopenharmony_ci        'root' : {
26337db96d56Sopenharmony_ci            'level' : 'WARNING',
26347db96d56Sopenharmony_ci        },
26357db96d56Sopenharmony_ci    }
26367db96d56Sopenharmony_ci
26377db96d56Sopenharmony_ci    # config8a disables existing loggers
26387db96d56Sopenharmony_ci    config8a = {
26397db96d56Sopenharmony_ci        'version': 1,
26407db96d56Sopenharmony_ci        'disable_existing_loggers' : True,
26417db96d56Sopenharmony_ci        'formatters': {
26427db96d56Sopenharmony_ci            'form1' : {
26437db96d56Sopenharmony_ci                'format' : '%(levelname)s ++ %(message)s',
26447db96d56Sopenharmony_ci            },
26457db96d56Sopenharmony_ci        },
26467db96d56Sopenharmony_ci        'handlers' : {
26477db96d56Sopenharmony_ci            'hand1' : {
26487db96d56Sopenharmony_ci                'class' : 'logging.StreamHandler',
26497db96d56Sopenharmony_ci                'formatter' : 'form1',
26507db96d56Sopenharmony_ci                'level' : 'NOTSET',
26517db96d56Sopenharmony_ci                'stream'  : 'ext://sys.stdout',
26527db96d56Sopenharmony_ci            },
26537db96d56Sopenharmony_ci        },
26547db96d56Sopenharmony_ci        'loggers' : {
26557db96d56Sopenharmony_ci            'compiler' : {
26567db96d56Sopenharmony_ci                'level' : 'DEBUG',
26577db96d56Sopenharmony_ci                'handlers' : ['hand1'],
26587db96d56Sopenharmony_ci            },
26597db96d56Sopenharmony_ci            'compiler.lexer' : {
26607db96d56Sopenharmony_ci            },
26617db96d56Sopenharmony_ci        },
26627db96d56Sopenharmony_ci        'root' : {
26637db96d56Sopenharmony_ci            'level' : 'WARNING',
26647db96d56Sopenharmony_ci        },
26657db96d56Sopenharmony_ci    }
26667db96d56Sopenharmony_ci
26677db96d56Sopenharmony_ci    config9 = {
26687db96d56Sopenharmony_ci        'version': 1,
26697db96d56Sopenharmony_ci        'formatters': {
26707db96d56Sopenharmony_ci            'form1' : {
26717db96d56Sopenharmony_ci                'format' : '%(levelname)s ++ %(message)s',
26727db96d56Sopenharmony_ci            },
26737db96d56Sopenharmony_ci        },
26747db96d56Sopenharmony_ci        'handlers' : {
26757db96d56Sopenharmony_ci            'hand1' : {
26767db96d56Sopenharmony_ci                'class' : 'logging.StreamHandler',
26777db96d56Sopenharmony_ci                'formatter' : 'form1',
26787db96d56Sopenharmony_ci                'level' : 'WARNING',
26797db96d56Sopenharmony_ci                'stream'  : 'ext://sys.stdout',
26807db96d56Sopenharmony_ci            },
26817db96d56Sopenharmony_ci        },
26827db96d56Sopenharmony_ci        'loggers' : {
26837db96d56Sopenharmony_ci            'compiler.parser' : {
26847db96d56Sopenharmony_ci                'level' : 'WARNING',
26857db96d56Sopenharmony_ci                'handlers' : ['hand1'],
26867db96d56Sopenharmony_ci            },
26877db96d56Sopenharmony_ci        },
26887db96d56Sopenharmony_ci        'root' : {
26897db96d56Sopenharmony_ci            'level' : 'NOTSET',
26907db96d56Sopenharmony_ci        },
26917db96d56Sopenharmony_ci    }
26927db96d56Sopenharmony_ci
26937db96d56Sopenharmony_ci    config9a = {
26947db96d56Sopenharmony_ci        'version': 1,
26957db96d56Sopenharmony_ci        'incremental' : True,
26967db96d56Sopenharmony_ci        'handlers' : {
26977db96d56Sopenharmony_ci            'hand1' : {
26987db96d56Sopenharmony_ci                'level' : 'WARNING',
26997db96d56Sopenharmony_ci            },
27007db96d56Sopenharmony_ci        },
27017db96d56Sopenharmony_ci        'loggers' : {
27027db96d56Sopenharmony_ci            'compiler.parser' : {
27037db96d56Sopenharmony_ci                'level' : 'INFO',
27047db96d56Sopenharmony_ci            },
27057db96d56Sopenharmony_ci        },
27067db96d56Sopenharmony_ci    }
27077db96d56Sopenharmony_ci
27087db96d56Sopenharmony_ci    config9b = {
27097db96d56Sopenharmony_ci        'version': 1,
27107db96d56Sopenharmony_ci        'incremental' : True,
27117db96d56Sopenharmony_ci        'handlers' : {
27127db96d56Sopenharmony_ci            'hand1' : {
27137db96d56Sopenharmony_ci                'level' : 'INFO',
27147db96d56Sopenharmony_ci            },
27157db96d56Sopenharmony_ci        },
27167db96d56Sopenharmony_ci        'loggers' : {
27177db96d56Sopenharmony_ci            'compiler.parser' : {
27187db96d56Sopenharmony_ci                'level' : 'INFO',
27197db96d56Sopenharmony_ci            },
27207db96d56Sopenharmony_ci        },
27217db96d56Sopenharmony_ci    }
27227db96d56Sopenharmony_ci
27237db96d56Sopenharmony_ci    # As config1 but with a filter added
27247db96d56Sopenharmony_ci    config10 = {
27257db96d56Sopenharmony_ci        'version': 1,
27267db96d56Sopenharmony_ci        'formatters': {
27277db96d56Sopenharmony_ci            'form1' : {
27287db96d56Sopenharmony_ci                'format' : '%(levelname)s ++ %(message)s',
27297db96d56Sopenharmony_ci            },
27307db96d56Sopenharmony_ci        },
27317db96d56Sopenharmony_ci        'filters' : {
27327db96d56Sopenharmony_ci            'filt1' : {
27337db96d56Sopenharmony_ci                'name' : 'compiler.parser',
27347db96d56Sopenharmony_ci            },
27357db96d56Sopenharmony_ci        },
27367db96d56Sopenharmony_ci        'handlers' : {
27377db96d56Sopenharmony_ci            'hand1' : {
27387db96d56Sopenharmony_ci                'class' : 'logging.StreamHandler',
27397db96d56Sopenharmony_ci                'formatter' : 'form1',
27407db96d56Sopenharmony_ci                'level' : 'NOTSET',
27417db96d56Sopenharmony_ci                'stream'  : 'ext://sys.stdout',
27427db96d56Sopenharmony_ci                'filters' : ['filt1'],
27437db96d56Sopenharmony_ci            },
27447db96d56Sopenharmony_ci        },
27457db96d56Sopenharmony_ci        'loggers' : {
27467db96d56Sopenharmony_ci            'compiler.parser' : {
27477db96d56Sopenharmony_ci                'level' : 'DEBUG',
27487db96d56Sopenharmony_ci                'filters' : ['filt1'],
27497db96d56Sopenharmony_ci            },
27507db96d56Sopenharmony_ci        },
27517db96d56Sopenharmony_ci        'root' : {
27527db96d56Sopenharmony_ci            'level' : 'WARNING',
27537db96d56Sopenharmony_ci            'handlers' : ['hand1'],
27547db96d56Sopenharmony_ci        },
27557db96d56Sopenharmony_ci    }
27567db96d56Sopenharmony_ci
27577db96d56Sopenharmony_ci    # As config1 but using cfg:// references
27587db96d56Sopenharmony_ci    config11 = {
27597db96d56Sopenharmony_ci        'version': 1,
27607db96d56Sopenharmony_ci        'true_formatters': {
27617db96d56Sopenharmony_ci            'form1' : {
27627db96d56Sopenharmony_ci                'format' : '%(levelname)s ++ %(message)s',
27637db96d56Sopenharmony_ci            },
27647db96d56Sopenharmony_ci        },
27657db96d56Sopenharmony_ci        'handler_configs': {
27667db96d56Sopenharmony_ci            'hand1' : {
27677db96d56Sopenharmony_ci                'class' : 'logging.StreamHandler',
27687db96d56Sopenharmony_ci                'formatter' : 'form1',
27697db96d56Sopenharmony_ci                'level' : 'NOTSET',
27707db96d56Sopenharmony_ci                'stream'  : 'ext://sys.stdout',
27717db96d56Sopenharmony_ci            },
27727db96d56Sopenharmony_ci        },
27737db96d56Sopenharmony_ci        'formatters' : 'cfg://true_formatters',
27747db96d56Sopenharmony_ci        'handlers' : {
27757db96d56Sopenharmony_ci            'hand1' : 'cfg://handler_configs[hand1]',
27767db96d56Sopenharmony_ci        },
27777db96d56Sopenharmony_ci        'loggers' : {
27787db96d56Sopenharmony_ci            'compiler.parser' : {
27797db96d56Sopenharmony_ci                'level' : 'DEBUG',
27807db96d56Sopenharmony_ci                'handlers' : ['hand1'],
27817db96d56Sopenharmony_ci            },
27827db96d56Sopenharmony_ci        },
27837db96d56Sopenharmony_ci        'root' : {
27847db96d56Sopenharmony_ci            'level' : 'WARNING',
27857db96d56Sopenharmony_ci        },
27867db96d56Sopenharmony_ci    }
27877db96d56Sopenharmony_ci
27887db96d56Sopenharmony_ci    # As config11 but missing the version key
27897db96d56Sopenharmony_ci    config12 = {
27907db96d56Sopenharmony_ci        'true_formatters': {
27917db96d56Sopenharmony_ci            'form1' : {
27927db96d56Sopenharmony_ci                'format' : '%(levelname)s ++ %(message)s',
27937db96d56Sopenharmony_ci            },
27947db96d56Sopenharmony_ci        },
27957db96d56Sopenharmony_ci        'handler_configs': {
27967db96d56Sopenharmony_ci            'hand1' : {
27977db96d56Sopenharmony_ci                'class' : 'logging.StreamHandler',
27987db96d56Sopenharmony_ci                'formatter' : 'form1',
27997db96d56Sopenharmony_ci                'level' : 'NOTSET',
28007db96d56Sopenharmony_ci                'stream'  : 'ext://sys.stdout',
28017db96d56Sopenharmony_ci            },
28027db96d56Sopenharmony_ci        },
28037db96d56Sopenharmony_ci        'formatters' : 'cfg://true_formatters',
28047db96d56Sopenharmony_ci        'handlers' : {
28057db96d56Sopenharmony_ci            'hand1' : 'cfg://handler_configs[hand1]',
28067db96d56Sopenharmony_ci        },
28077db96d56Sopenharmony_ci        'loggers' : {
28087db96d56Sopenharmony_ci            'compiler.parser' : {
28097db96d56Sopenharmony_ci                'level' : 'DEBUG',
28107db96d56Sopenharmony_ci                'handlers' : ['hand1'],
28117db96d56Sopenharmony_ci            },
28127db96d56Sopenharmony_ci        },
28137db96d56Sopenharmony_ci        'root' : {
28147db96d56Sopenharmony_ci            'level' : 'WARNING',
28157db96d56Sopenharmony_ci        },
28167db96d56Sopenharmony_ci    }
28177db96d56Sopenharmony_ci
28187db96d56Sopenharmony_ci    # As config11 but using an unsupported version
28197db96d56Sopenharmony_ci    config13 = {
28207db96d56Sopenharmony_ci        'version': 2,
28217db96d56Sopenharmony_ci        'true_formatters': {
28227db96d56Sopenharmony_ci            'form1' : {
28237db96d56Sopenharmony_ci                'format' : '%(levelname)s ++ %(message)s',
28247db96d56Sopenharmony_ci            },
28257db96d56Sopenharmony_ci        },
28267db96d56Sopenharmony_ci        'handler_configs': {
28277db96d56Sopenharmony_ci            'hand1' : {
28287db96d56Sopenharmony_ci                'class' : 'logging.StreamHandler',
28297db96d56Sopenharmony_ci                'formatter' : 'form1',
28307db96d56Sopenharmony_ci                'level' : 'NOTSET',
28317db96d56Sopenharmony_ci                'stream'  : 'ext://sys.stdout',
28327db96d56Sopenharmony_ci            },
28337db96d56Sopenharmony_ci        },
28347db96d56Sopenharmony_ci        'formatters' : 'cfg://true_formatters',
28357db96d56Sopenharmony_ci        'handlers' : {
28367db96d56Sopenharmony_ci            'hand1' : 'cfg://handler_configs[hand1]',
28377db96d56Sopenharmony_ci        },
28387db96d56Sopenharmony_ci        'loggers' : {
28397db96d56Sopenharmony_ci            'compiler.parser' : {
28407db96d56Sopenharmony_ci                'level' : 'DEBUG',
28417db96d56Sopenharmony_ci                'handlers' : ['hand1'],
28427db96d56Sopenharmony_ci            },
28437db96d56Sopenharmony_ci        },
28447db96d56Sopenharmony_ci        'root' : {
28457db96d56Sopenharmony_ci            'level' : 'WARNING',
28467db96d56Sopenharmony_ci        },
28477db96d56Sopenharmony_ci    }
28487db96d56Sopenharmony_ci
28497db96d56Sopenharmony_ci    # As config0, but with properties
28507db96d56Sopenharmony_ci    config14 = {
28517db96d56Sopenharmony_ci        'version': 1,
28527db96d56Sopenharmony_ci        'formatters': {
28537db96d56Sopenharmony_ci            'form1' : {
28547db96d56Sopenharmony_ci                'format' : '%(levelname)s ++ %(message)s',
28557db96d56Sopenharmony_ci            },
28567db96d56Sopenharmony_ci        },
28577db96d56Sopenharmony_ci        'handlers' : {
28587db96d56Sopenharmony_ci            'hand1' : {
28597db96d56Sopenharmony_ci                'class' : 'logging.StreamHandler',
28607db96d56Sopenharmony_ci                'formatter' : 'form1',
28617db96d56Sopenharmony_ci                'level' : 'NOTSET',
28627db96d56Sopenharmony_ci                'stream'  : 'ext://sys.stdout',
28637db96d56Sopenharmony_ci                '.': {
28647db96d56Sopenharmony_ci                    'foo': 'bar',
28657db96d56Sopenharmony_ci                    'terminator': '!\n',
28667db96d56Sopenharmony_ci                }
28677db96d56Sopenharmony_ci            },
28687db96d56Sopenharmony_ci        },
28697db96d56Sopenharmony_ci        'root' : {
28707db96d56Sopenharmony_ci            'level' : 'WARNING',
28717db96d56Sopenharmony_ci            'handlers' : ['hand1'],
28727db96d56Sopenharmony_ci        },
28737db96d56Sopenharmony_ci    }
28747db96d56Sopenharmony_ci
28757db96d56Sopenharmony_ci    out_of_order = {
28767db96d56Sopenharmony_ci        "version": 1,
28777db96d56Sopenharmony_ci        "formatters": {
28787db96d56Sopenharmony_ci            "mySimpleFormatter": {
28797db96d56Sopenharmony_ci                "format": "%(asctime)s (%(name)s) %(levelname)s: %(message)s",
28807db96d56Sopenharmony_ci                "style": "$"
28817db96d56Sopenharmony_ci            }
28827db96d56Sopenharmony_ci        },
28837db96d56Sopenharmony_ci        "handlers": {
28847db96d56Sopenharmony_ci            "fileGlobal": {
28857db96d56Sopenharmony_ci                "class": "logging.StreamHandler",
28867db96d56Sopenharmony_ci                "level": "DEBUG",
28877db96d56Sopenharmony_ci                "formatter": "mySimpleFormatter"
28887db96d56Sopenharmony_ci            },
28897db96d56Sopenharmony_ci            "bufferGlobal": {
28907db96d56Sopenharmony_ci                "class": "logging.handlers.MemoryHandler",
28917db96d56Sopenharmony_ci                "capacity": 5,
28927db96d56Sopenharmony_ci                "formatter": "mySimpleFormatter",
28937db96d56Sopenharmony_ci                "target": "fileGlobal",
28947db96d56Sopenharmony_ci                "level": "DEBUG"
28957db96d56Sopenharmony_ci                }
28967db96d56Sopenharmony_ci        },
28977db96d56Sopenharmony_ci        "loggers": {
28987db96d56Sopenharmony_ci            "mymodule": {
28997db96d56Sopenharmony_ci                "level": "DEBUG",
29007db96d56Sopenharmony_ci                "handlers": ["bufferGlobal"],
29017db96d56Sopenharmony_ci                "propagate": "true"
29027db96d56Sopenharmony_ci            }
29037db96d56Sopenharmony_ci        }
29047db96d56Sopenharmony_ci    }
29057db96d56Sopenharmony_ci
29067db96d56Sopenharmony_ci    # Configuration with custom logging.Formatter subclass as '()' key and 'validate' set to False
29077db96d56Sopenharmony_ci    custom_formatter_class_validate = {
29087db96d56Sopenharmony_ci        'version': 1,
29097db96d56Sopenharmony_ci        'formatters': {
29107db96d56Sopenharmony_ci            'form1': {
29117db96d56Sopenharmony_ci                '()': __name__ + '.ExceptionFormatter',
29127db96d56Sopenharmony_ci                'format': '%(levelname)s:%(name)s:%(message)s',
29137db96d56Sopenharmony_ci                'validate': False,
29147db96d56Sopenharmony_ci            },
29157db96d56Sopenharmony_ci        },
29167db96d56Sopenharmony_ci        'handlers' : {
29177db96d56Sopenharmony_ci            'hand1' : {
29187db96d56Sopenharmony_ci                'class': 'logging.StreamHandler',
29197db96d56Sopenharmony_ci                'formatter': 'form1',
29207db96d56Sopenharmony_ci                'level': 'NOTSET',
29217db96d56Sopenharmony_ci                'stream': 'ext://sys.stdout',
29227db96d56Sopenharmony_ci            },
29237db96d56Sopenharmony_ci        },
29247db96d56Sopenharmony_ci        "loggers": {
29257db96d56Sopenharmony_ci            "my_test_logger_custom_formatter": {
29267db96d56Sopenharmony_ci                "level": "DEBUG",
29277db96d56Sopenharmony_ci                "handlers": ["hand1"],
29287db96d56Sopenharmony_ci                "propagate": "true"
29297db96d56Sopenharmony_ci            }
29307db96d56Sopenharmony_ci        }
29317db96d56Sopenharmony_ci    }
29327db96d56Sopenharmony_ci
29337db96d56Sopenharmony_ci    # Configuration with custom logging.Formatter subclass as 'class' key and 'validate' set to False
29347db96d56Sopenharmony_ci    custom_formatter_class_validate2 = {
29357db96d56Sopenharmony_ci        'version': 1,
29367db96d56Sopenharmony_ci        'formatters': {
29377db96d56Sopenharmony_ci            'form1': {
29387db96d56Sopenharmony_ci                'class': __name__ + '.ExceptionFormatter',
29397db96d56Sopenharmony_ci                'format': '%(levelname)s:%(name)s:%(message)s',
29407db96d56Sopenharmony_ci                'validate': False,
29417db96d56Sopenharmony_ci            },
29427db96d56Sopenharmony_ci        },
29437db96d56Sopenharmony_ci        'handlers' : {
29447db96d56Sopenharmony_ci            'hand1' : {
29457db96d56Sopenharmony_ci                'class': 'logging.StreamHandler',
29467db96d56Sopenharmony_ci                'formatter': 'form1',
29477db96d56Sopenharmony_ci                'level': 'NOTSET',
29487db96d56Sopenharmony_ci                'stream': 'ext://sys.stdout',
29497db96d56Sopenharmony_ci            },
29507db96d56Sopenharmony_ci        },
29517db96d56Sopenharmony_ci        "loggers": {
29527db96d56Sopenharmony_ci            "my_test_logger_custom_formatter": {
29537db96d56Sopenharmony_ci                "level": "DEBUG",
29547db96d56Sopenharmony_ci                "handlers": ["hand1"],
29557db96d56Sopenharmony_ci                "propagate": "true"
29567db96d56Sopenharmony_ci            }
29577db96d56Sopenharmony_ci        }
29587db96d56Sopenharmony_ci    }
29597db96d56Sopenharmony_ci
29607db96d56Sopenharmony_ci    # Configuration with custom class that is not inherited from logging.Formatter
29617db96d56Sopenharmony_ci    custom_formatter_class_validate3 = {
29627db96d56Sopenharmony_ci        'version': 1,
29637db96d56Sopenharmony_ci        'formatters': {
29647db96d56Sopenharmony_ci            'form1': {
29657db96d56Sopenharmony_ci                'class': __name__ + '.myCustomFormatter',
29667db96d56Sopenharmony_ci                'format': '%(levelname)s:%(name)s:%(message)s',
29677db96d56Sopenharmony_ci                'validate': False,
29687db96d56Sopenharmony_ci            },
29697db96d56Sopenharmony_ci        },
29707db96d56Sopenharmony_ci        'handlers' : {
29717db96d56Sopenharmony_ci            'hand1' : {
29727db96d56Sopenharmony_ci                'class': 'logging.StreamHandler',
29737db96d56Sopenharmony_ci                'formatter': 'form1',
29747db96d56Sopenharmony_ci                'level': 'NOTSET',
29757db96d56Sopenharmony_ci                'stream': 'ext://sys.stdout',
29767db96d56Sopenharmony_ci            },
29777db96d56Sopenharmony_ci        },
29787db96d56Sopenharmony_ci        "loggers": {
29797db96d56Sopenharmony_ci            "my_test_logger_custom_formatter": {
29807db96d56Sopenharmony_ci                "level": "DEBUG",
29817db96d56Sopenharmony_ci                "handlers": ["hand1"],
29827db96d56Sopenharmony_ci                "propagate": "true"
29837db96d56Sopenharmony_ci            }
29847db96d56Sopenharmony_ci        }
29857db96d56Sopenharmony_ci    }
29867db96d56Sopenharmony_ci
29877db96d56Sopenharmony_ci    # Configuration with custom function and 'validate' set to False
29887db96d56Sopenharmony_ci    custom_formatter_with_function = {
29897db96d56Sopenharmony_ci        'version': 1,
29907db96d56Sopenharmony_ci        'formatters': {
29917db96d56Sopenharmony_ci            'form1': {
29927db96d56Sopenharmony_ci                '()': formatFunc,
29937db96d56Sopenharmony_ci                'format': '%(levelname)s:%(name)s:%(message)s',
29947db96d56Sopenharmony_ci                'validate': False,
29957db96d56Sopenharmony_ci            },
29967db96d56Sopenharmony_ci        },
29977db96d56Sopenharmony_ci        'handlers' : {
29987db96d56Sopenharmony_ci            'hand1' : {
29997db96d56Sopenharmony_ci                'class': 'logging.StreamHandler',
30007db96d56Sopenharmony_ci                'formatter': 'form1',
30017db96d56Sopenharmony_ci                'level': 'NOTSET',
30027db96d56Sopenharmony_ci                'stream': 'ext://sys.stdout',
30037db96d56Sopenharmony_ci            },
30047db96d56Sopenharmony_ci        },
30057db96d56Sopenharmony_ci        "loggers": {
30067db96d56Sopenharmony_ci            "my_test_logger_custom_formatter": {
30077db96d56Sopenharmony_ci                "level": "DEBUG",
30087db96d56Sopenharmony_ci                "handlers": ["hand1"],
30097db96d56Sopenharmony_ci                "propagate": "true"
30107db96d56Sopenharmony_ci            }
30117db96d56Sopenharmony_ci        }
30127db96d56Sopenharmony_ci    }
30137db96d56Sopenharmony_ci
30147db96d56Sopenharmony_ci    def apply_config(self, conf):
30157db96d56Sopenharmony_ci        logging.config.dictConfig(conf)
30167db96d56Sopenharmony_ci
30177db96d56Sopenharmony_ci    def test_config0_ok(self):
30187db96d56Sopenharmony_ci        # A simple config which overrides the default settings.
30197db96d56Sopenharmony_ci        with support.captured_stdout() as output:
30207db96d56Sopenharmony_ci            self.apply_config(self.config0)
30217db96d56Sopenharmony_ci            logger = logging.getLogger()
30227db96d56Sopenharmony_ci            # Won't output anything
30237db96d56Sopenharmony_ci            logger.info(self.next_message())
30247db96d56Sopenharmony_ci            # Outputs a message
30257db96d56Sopenharmony_ci            logger.error(self.next_message())
30267db96d56Sopenharmony_ci            self.assert_log_lines([
30277db96d56Sopenharmony_ci                ('ERROR', '2'),
30287db96d56Sopenharmony_ci            ], stream=output)
30297db96d56Sopenharmony_ci            # Original logger output is empty.
30307db96d56Sopenharmony_ci            self.assert_log_lines([])
30317db96d56Sopenharmony_ci
30327db96d56Sopenharmony_ci    def test_config1_ok(self, config=config1):
30337db96d56Sopenharmony_ci        # A config defining a sub-parser as well.
30347db96d56Sopenharmony_ci        with support.captured_stdout() as output:
30357db96d56Sopenharmony_ci            self.apply_config(config)
30367db96d56Sopenharmony_ci            logger = logging.getLogger("compiler.parser")
30377db96d56Sopenharmony_ci            # Both will output a message
30387db96d56Sopenharmony_ci            logger.info(self.next_message())
30397db96d56Sopenharmony_ci            logger.error(self.next_message())
30407db96d56Sopenharmony_ci            self.assert_log_lines([
30417db96d56Sopenharmony_ci                ('INFO', '1'),
30427db96d56Sopenharmony_ci                ('ERROR', '2'),
30437db96d56Sopenharmony_ci            ], stream=output)
30447db96d56Sopenharmony_ci            # Original logger output is empty.
30457db96d56Sopenharmony_ci            self.assert_log_lines([])
30467db96d56Sopenharmony_ci
30477db96d56Sopenharmony_ci    def test_config2_failure(self):
30487db96d56Sopenharmony_ci        # A simple config which overrides the default settings.
30497db96d56Sopenharmony_ci        self.assertRaises(Exception, self.apply_config, self.config2)
30507db96d56Sopenharmony_ci
30517db96d56Sopenharmony_ci    def test_config2a_failure(self):
30527db96d56Sopenharmony_ci        # A simple config which overrides the default settings.
30537db96d56Sopenharmony_ci        self.assertRaises(Exception, self.apply_config, self.config2a)
30547db96d56Sopenharmony_ci
30557db96d56Sopenharmony_ci    def test_config2b_failure(self):
30567db96d56Sopenharmony_ci        # A simple config which overrides the default settings.
30577db96d56Sopenharmony_ci        self.assertRaises(Exception, self.apply_config, self.config2b)
30587db96d56Sopenharmony_ci
30597db96d56Sopenharmony_ci    def test_config3_failure(self):
30607db96d56Sopenharmony_ci        # A simple config which overrides the default settings.
30617db96d56Sopenharmony_ci        self.assertRaises(Exception, self.apply_config, self.config3)
30627db96d56Sopenharmony_ci
30637db96d56Sopenharmony_ci    def test_config4_ok(self):
30647db96d56Sopenharmony_ci        # A config specifying a custom formatter class.
30657db96d56Sopenharmony_ci        with support.captured_stdout() as output:
30667db96d56Sopenharmony_ci            self.apply_config(self.config4)
30677db96d56Sopenharmony_ci            #logger = logging.getLogger()
30687db96d56Sopenharmony_ci            try:
30697db96d56Sopenharmony_ci                raise RuntimeError()
30707db96d56Sopenharmony_ci            except RuntimeError:
30717db96d56Sopenharmony_ci                logging.exception("just testing")
30727db96d56Sopenharmony_ci            sys.stdout.seek(0)
30737db96d56Sopenharmony_ci            self.assertEqual(output.getvalue(),
30747db96d56Sopenharmony_ci                "ERROR:root:just testing\nGot a [RuntimeError]\n")
30757db96d56Sopenharmony_ci            # Original logger output is empty
30767db96d56Sopenharmony_ci            self.assert_log_lines([])
30777db96d56Sopenharmony_ci
30787db96d56Sopenharmony_ci    def test_config4a_ok(self):
30797db96d56Sopenharmony_ci        # A config specifying a custom formatter class.
30807db96d56Sopenharmony_ci        with support.captured_stdout() as output:
30817db96d56Sopenharmony_ci            self.apply_config(self.config4a)
30827db96d56Sopenharmony_ci            #logger = logging.getLogger()
30837db96d56Sopenharmony_ci            try:
30847db96d56Sopenharmony_ci                raise RuntimeError()
30857db96d56Sopenharmony_ci            except RuntimeError:
30867db96d56Sopenharmony_ci                logging.exception("just testing")
30877db96d56Sopenharmony_ci            sys.stdout.seek(0)
30887db96d56Sopenharmony_ci            self.assertEqual(output.getvalue(),
30897db96d56Sopenharmony_ci                "ERROR:root:just testing\nGot a [RuntimeError]\n")
30907db96d56Sopenharmony_ci            # Original logger output is empty
30917db96d56Sopenharmony_ci            self.assert_log_lines([])
30927db96d56Sopenharmony_ci
30937db96d56Sopenharmony_ci    def test_config5_ok(self):
30947db96d56Sopenharmony_ci        self.test_config1_ok(config=self.config5)
30957db96d56Sopenharmony_ci
30967db96d56Sopenharmony_ci    def test_config6_failure(self):
30977db96d56Sopenharmony_ci        self.assertRaises(Exception, self.apply_config, self.config6)
30987db96d56Sopenharmony_ci
30997db96d56Sopenharmony_ci    def test_config7_ok(self):
31007db96d56Sopenharmony_ci        with support.captured_stdout() as output:
31017db96d56Sopenharmony_ci            self.apply_config(self.config1)
31027db96d56Sopenharmony_ci            logger = logging.getLogger("compiler.parser")
31037db96d56Sopenharmony_ci            # Both will output a message
31047db96d56Sopenharmony_ci            logger.info(self.next_message())
31057db96d56Sopenharmony_ci            logger.error(self.next_message())
31067db96d56Sopenharmony_ci            self.assert_log_lines([
31077db96d56Sopenharmony_ci                ('INFO', '1'),
31087db96d56Sopenharmony_ci                ('ERROR', '2'),
31097db96d56Sopenharmony_ci            ], stream=output)
31107db96d56Sopenharmony_ci            # Original logger output is empty.
31117db96d56Sopenharmony_ci            self.assert_log_lines([])
31127db96d56Sopenharmony_ci        with support.captured_stdout() as output:
31137db96d56Sopenharmony_ci            self.apply_config(self.config7)
31147db96d56Sopenharmony_ci            logger = logging.getLogger("compiler.parser")
31157db96d56Sopenharmony_ci            self.assertTrue(logger.disabled)
31167db96d56Sopenharmony_ci            logger = logging.getLogger("compiler.lexer")
31177db96d56Sopenharmony_ci            # Both will output a message
31187db96d56Sopenharmony_ci            logger.info(self.next_message())
31197db96d56Sopenharmony_ci            logger.error(self.next_message())
31207db96d56Sopenharmony_ci            self.assert_log_lines([
31217db96d56Sopenharmony_ci                ('INFO', '3'),
31227db96d56Sopenharmony_ci                ('ERROR', '4'),
31237db96d56Sopenharmony_ci            ], stream=output)
31247db96d56Sopenharmony_ci            # Original logger output is empty.
31257db96d56Sopenharmony_ci            self.assert_log_lines([])
31267db96d56Sopenharmony_ci
31277db96d56Sopenharmony_ci    # Same as test_config_7_ok but don't disable old loggers.
31287db96d56Sopenharmony_ci    def test_config_8_ok(self):
31297db96d56Sopenharmony_ci        with support.captured_stdout() as output:
31307db96d56Sopenharmony_ci            self.apply_config(self.config1)
31317db96d56Sopenharmony_ci            logger = logging.getLogger("compiler.parser")
31327db96d56Sopenharmony_ci            # All will output a message
31337db96d56Sopenharmony_ci            logger.info(self.next_message())
31347db96d56Sopenharmony_ci            logger.error(self.next_message())
31357db96d56Sopenharmony_ci            self.assert_log_lines([
31367db96d56Sopenharmony_ci                ('INFO', '1'),
31377db96d56Sopenharmony_ci                ('ERROR', '2'),
31387db96d56Sopenharmony_ci            ], stream=output)
31397db96d56Sopenharmony_ci            # Original logger output is empty.
31407db96d56Sopenharmony_ci            self.assert_log_lines([])
31417db96d56Sopenharmony_ci        with support.captured_stdout() as output:
31427db96d56Sopenharmony_ci            self.apply_config(self.config8)
31437db96d56Sopenharmony_ci            logger = logging.getLogger("compiler.parser")
31447db96d56Sopenharmony_ci            self.assertFalse(logger.disabled)
31457db96d56Sopenharmony_ci            # Both will output a message
31467db96d56Sopenharmony_ci            logger.info(self.next_message())
31477db96d56Sopenharmony_ci            logger.error(self.next_message())
31487db96d56Sopenharmony_ci            logger = logging.getLogger("compiler.lexer")
31497db96d56Sopenharmony_ci            # Both will output a message
31507db96d56Sopenharmony_ci            logger.info(self.next_message())
31517db96d56Sopenharmony_ci            logger.error(self.next_message())
31527db96d56Sopenharmony_ci            self.assert_log_lines([
31537db96d56Sopenharmony_ci                ('INFO', '3'),
31547db96d56Sopenharmony_ci                ('ERROR', '4'),
31557db96d56Sopenharmony_ci                ('INFO', '5'),
31567db96d56Sopenharmony_ci                ('ERROR', '6'),
31577db96d56Sopenharmony_ci            ], stream=output)
31587db96d56Sopenharmony_ci            # Original logger output is empty.
31597db96d56Sopenharmony_ci            self.assert_log_lines([])
31607db96d56Sopenharmony_ci
31617db96d56Sopenharmony_ci    def test_config_8a_ok(self):
31627db96d56Sopenharmony_ci        with support.captured_stdout() as output:
31637db96d56Sopenharmony_ci            self.apply_config(self.config1a)
31647db96d56Sopenharmony_ci            logger = logging.getLogger("compiler.parser")
31657db96d56Sopenharmony_ci            # See issue #11424. compiler-hyphenated sorts
31667db96d56Sopenharmony_ci            # between compiler and compiler.xyz and this
31677db96d56Sopenharmony_ci            # was preventing compiler.xyz from being included
31687db96d56Sopenharmony_ci            # in the child loggers of compiler because of an
31697db96d56Sopenharmony_ci            # overzealous loop termination condition.
31707db96d56Sopenharmony_ci            hyphenated = logging.getLogger('compiler-hyphenated')
31717db96d56Sopenharmony_ci            # All will output a message
31727db96d56Sopenharmony_ci            logger.info(self.next_message())
31737db96d56Sopenharmony_ci            logger.error(self.next_message())
31747db96d56Sopenharmony_ci            hyphenated.critical(self.next_message())
31757db96d56Sopenharmony_ci            self.assert_log_lines([
31767db96d56Sopenharmony_ci                ('INFO', '1'),
31777db96d56Sopenharmony_ci                ('ERROR', '2'),
31787db96d56Sopenharmony_ci                ('CRITICAL', '3'),
31797db96d56Sopenharmony_ci            ], stream=output)
31807db96d56Sopenharmony_ci            # Original logger output is empty.
31817db96d56Sopenharmony_ci            self.assert_log_lines([])
31827db96d56Sopenharmony_ci        with support.captured_stdout() as output:
31837db96d56Sopenharmony_ci            self.apply_config(self.config8a)
31847db96d56Sopenharmony_ci            logger = logging.getLogger("compiler.parser")
31857db96d56Sopenharmony_ci            self.assertFalse(logger.disabled)
31867db96d56Sopenharmony_ci            # Both will output a message
31877db96d56Sopenharmony_ci            logger.info(self.next_message())
31887db96d56Sopenharmony_ci            logger.error(self.next_message())
31897db96d56Sopenharmony_ci            logger = logging.getLogger("compiler.lexer")
31907db96d56Sopenharmony_ci            # Both will output a message
31917db96d56Sopenharmony_ci            logger.info(self.next_message())
31927db96d56Sopenharmony_ci            logger.error(self.next_message())
31937db96d56Sopenharmony_ci            # Will not appear
31947db96d56Sopenharmony_ci            hyphenated.critical(self.next_message())
31957db96d56Sopenharmony_ci            self.assert_log_lines([
31967db96d56Sopenharmony_ci                ('INFO', '4'),
31977db96d56Sopenharmony_ci                ('ERROR', '5'),
31987db96d56Sopenharmony_ci                ('INFO', '6'),
31997db96d56Sopenharmony_ci                ('ERROR', '7'),
32007db96d56Sopenharmony_ci            ], stream=output)
32017db96d56Sopenharmony_ci            # Original logger output is empty.
32027db96d56Sopenharmony_ci            self.assert_log_lines([])
32037db96d56Sopenharmony_ci
32047db96d56Sopenharmony_ci    def test_config_9_ok(self):
32057db96d56Sopenharmony_ci        with support.captured_stdout() as output:
32067db96d56Sopenharmony_ci            self.apply_config(self.config9)
32077db96d56Sopenharmony_ci            logger = logging.getLogger("compiler.parser")
32087db96d56Sopenharmony_ci            # Nothing will be output since both handler and logger are set to WARNING
32097db96d56Sopenharmony_ci            logger.info(self.next_message())
32107db96d56Sopenharmony_ci            self.assert_log_lines([], stream=output)
32117db96d56Sopenharmony_ci            self.apply_config(self.config9a)
32127db96d56Sopenharmony_ci            # Nothing will be output since handler is still set to WARNING
32137db96d56Sopenharmony_ci            logger.info(self.next_message())
32147db96d56Sopenharmony_ci            self.assert_log_lines([], stream=output)
32157db96d56Sopenharmony_ci            self.apply_config(self.config9b)
32167db96d56Sopenharmony_ci            # Message should now be output
32177db96d56Sopenharmony_ci            logger.info(self.next_message())
32187db96d56Sopenharmony_ci            self.assert_log_lines([
32197db96d56Sopenharmony_ci                ('INFO', '3'),
32207db96d56Sopenharmony_ci            ], stream=output)
32217db96d56Sopenharmony_ci
32227db96d56Sopenharmony_ci    def test_config_10_ok(self):
32237db96d56Sopenharmony_ci        with support.captured_stdout() as output:
32247db96d56Sopenharmony_ci            self.apply_config(self.config10)
32257db96d56Sopenharmony_ci            logger = logging.getLogger("compiler.parser")
32267db96d56Sopenharmony_ci            logger.warning(self.next_message())
32277db96d56Sopenharmony_ci            logger = logging.getLogger('compiler')
32287db96d56Sopenharmony_ci            # Not output, because filtered
32297db96d56Sopenharmony_ci            logger.warning(self.next_message())
32307db96d56Sopenharmony_ci            logger = logging.getLogger('compiler.lexer')
32317db96d56Sopenharmony_ci            # Not output, because filtered
32327db96d56Sopenharmony_ci            logger.warning(self.next_message())
32337db96d56Sopenharmony_ci            logger = logging.getLogger("compiler.parser.codegen")
32347db96d56Sopenharmony_ci            # Output, as not filtered
32357db96d56Sopenharmony_ci            logger.error(self.next_message())
32367db96d56Sopenharmony_ci            self.assert_log_lines([
32377db96d56Sopenharmony_ci                ('WARNING', '1'),
32387db96d56Sopenharmony_ci                ('ERROR', '4'),
32397db96d56Sopenharmony_ci            ], stream=output)
32407db96d56Sopenharmony_ci
32417db96d56Sopenharmony_ci    def test_config11_ok(self):
32427db96d56Sopenharmony_ci        self.test_config1_ok(self.config11)
32437db96d56Sopenharmony_ci
32447db96d56Sopenharmony_ci    def test_config12_failure(self):
32457db96d56Sopenharmony_ci        self.assertRaises(Exception, self.apply_config, self.config12)
32467db96d56Sopenharmony_ci
32477db96d56Sopenharmony_ci    def test_config13_failure(self):
32487db96d56Sopenharmony_ci        self.assertRaises(Exception, self.apply_config, self.config13)
32497db96d56Sopenharmony_ci
32507db96d56Sopenharmony_ci    def test_config14_ok(self):
32517db96d56Sopenharmony_ci        with support.captured_stdout() as output:
32527db96d56Sopenharmony_ci            self.apply_config(self.config14)
32537db96d56Sopenharmony_ci            h = logging._handlers['hand1']
32547db96d56Sopenharmony_ci            self.assertEqual(h.foo, 'bar')
32557db96d56Sopenharmony_ci            self.assertEqual(h.terminator, '!\n')
32567db96d56Sopenharmony_ci            logging.warning('Exclamation')
32577db96d56Sopenharmony_ci            self.assertTrue(output.getvalue().endswith('Exclamation!\n'))
32587db96d56Sopenharmony_ci
32597db96d56Sopenharmony_ci    def test_config15_ok(self):
32607db96d56Sopenharmony_ci
32617db96d56Sopenharmony_ci        def cleanup(h1, fn):
32627db96d56Sopenharmony_ci            h1.close()
32637db96d56Sopenharmony_ci            os.remove(fn)
32647db96d56Sopenharmony_ci
32657db96d56Sopenharmony_ci        with self.check_no_resource_warning():
32667db96d56Sopenharmony_ci            fd, fn = tempfile.mkstemp(".log", "test_logging-X-")
32677db96d56Sopenharmony_ci            os.close(fd)
32687db96d56Sopenharmony_ci
32697db96d56Sopenharmony_ci            config = {
32707db96d56Sopenharmony_ci                "version": 1,
32717db96d56Sopenharmony_ci                "handlers": {
32727db96d56Sopenharmony_ci                    "file": {
32737db96d56Sopenharmony_ci                        "class": "logging.FileHandler",
32747db96d56Sopenharmony_ci                        "filename": fn,
32757db96d56Sopenharmony_ci                        "encoding": "utf-8",
32767db96d56Sopenharmony_ci                    }
32777db96d56Sopenharmony_ci                },
32787db96d56Sopenharmony_ci                "root": {
32797db96d56Sopenharmony_ci                    "handlers": ["file"]
32807db96d56Sopenharmony_ci                }
32817db96d56Sopenharmony_ci            }
32827db96d56Sopenharmony_ci
32837db96d56Sopenharmony_ci            self.apply_config(config)
32847db96d56Sopenharmony_ci            self.apply_config(config)
32857db96d56Sopenharmony_ci
32867db96d56Sopenharmony_ci        handler = logging.root.handlers[0]
32877db96d56Sopenharmony_ci        self.addCleanup(cleanup, handler, fn)
32887db96d56Sopenharmony_ci
32897db96d56Sopenharmony_ci    def setup_via_listener(self, text, verify=None):
32907db96d56Sopenharmony_ci        text = text.encode("utf-8")
32917db96d56Sopenharmony_ci        # Ask for a randomly assigned port (by using port 0)
32927db96d56Sopenharmony_ci        t = logging.config.listen(0, verify)
32937db96d56Sopenharmony_ci        t.start()
32947db96d56Sopenharmony_ci        t.ready.wait()
32957db96d56Sopenharmony_ci        # Now get the port allocated
32967db96d56Sopenharmony_ci        port = t.port
32977db96d56Sopenharmony_ci        t.ready.clear()
32987db96d56Sopenharmony_ci        try:
32997db96d56Sopenharmony_ci            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
33007db96d56Sopenharmony_ci            sock.settimeout(2.0)
33017db96d56Sopenharmony_ci            sock.connect(('localhost', port))
33027db96d56Sopenharmony_ci
33037db96d56Sopenharmony_ci            slen = struct.pack('>L', len(text))
33047db96d56Sopenharmony_ci            s = slen + text
33057db96d56Sopenharmony_ci            sentsofar = 0
33067db96d56Sopenharmony_ci            left = len(s)
33077db96d56Sopenharmony_ci            while left > 0:
33087db96d56Sopenharmony_ci                sent = sock.send(s[sentsofar:])
33097db96d56Sopenharmony_ci                sentsofar += sent
33107db96d56Sopenharmony_ci                left -= sent
33117db96d56Sopenharmony_ci            sock.close()
33127db96d56Sopenharmony_ci        finally:
33137db96d56Sopenharmony_ci            t.ready.wait(2.0)
33147db96d56Sopenharmony_ci            logging.config.stopListening()
33157db96d56Sopenharmony_ci            threading_helper.join_thread(t)
33167db96d56Sopenharmony_ci
33177db96d56Sopenharmony_ci    @support.requires_working_socket()
33187db96d56Sopenharmony_ci    def test_listen_config_10_ok(self):
33197db96d56Sopenharmony_ci        with support.captured_stdout() as output:
33207db96d56Sopenharmony_ci            self.setup_via_listener(json.dumps(self.config10))
33217db96d56Sopenharmony_ci            logger = logging.getLogger("compiler.parser")
33227db96d56Sopenharmony_ci            logger.warning(self.next_message())
33237db96d56Sopenharmony_ci            logger = logging.getLogger('compiler')
33247db96d56Sopenharmony_ci            # Not output, because filtered
33257db96d56Sopenharmony_ci            logger.warning(self.next_message())
33267db96d56Sopenharmony_ci            logger = logging.getLogger('compiler.lexer')
33277db96d56Sopenharmony_ci            # Not output, because filtered
33287db96d56Sopenharmony_ci            logger.warning(self.next_message())
33297db96d56Sopenharmony_ci            logger = logging.getLogger("compiler.parser.codegen")
33307db96d56Sopenharmony_ci            # Output, as not filtered
33317db96d56Sopenharmony_ci            logger.error(self.next_message())
33327db96d56Sopenharmony_ci            self.assert_log_lines([
33337db96d56Sopenharmony_ci                ('WARNING', '1'),
33347db96d56Sopenharmony_ci                ('ERROR', '4'),
33357db96d56Sopenharmony_ci            ], stream=output)
33367db96d56Sopenharmony_ci
33377db96d56Sopenharmony_ci    @support.requires_working_socket()
33387db96d56Sopenharmony_ci    def test_listen_config_1_ok(self):
33397db96d56Sopenharmony_ci        with support.captured_stdout() as output:
33407db96d56Sopenharmony_ci            self.setup_via_listener(textwrap.dedent(ConfigFileTest.config1))
33417db96d56Sopenharmony_ci            logger = logging.getLogger("compiler.parser")
33427db96d56Sopenharmony_ci            # Both will output a message
33437db96d56Sopenharmony_ci            logger.info(self.next_message())
33447db96d56Sopenharmony_ci            logger.error(self.next_message())
33457db96d56Sopenharmony_ci            self.assert_log_lines([
33467db96d56Sopenharmony_ci                ('INFO', '1'),
33477db96d56Sopenharmony_ci                ('ERROR', '2'),
33487db96d56Sopenharmony_ci            ], stream=output)
33497db96d56Sopenharmony_ci            # Original logger output is empty.
33507db96d56Sopenharmony_ci            self.assert_log_lines([])
33517db96d56Sopenharmony_ci
33527db96d56Sopenharmony_ci    @support.requires_working_socket()
33537db96d56Sopenharmony_ci    def test_listen_verify(self):
33547db96d56Sopenharmony_ci
33557db96d56Sopenharmony_ci        def verify_fail(stuff):
33567db96d56Sopenharmony_ci            return None
33577db96d56Sopenharmony_ci
33587db96d56Sopenharmony_ci        def verify_reverse(stuff):
33597db96d56Sopenharmony_ci            return stuff[::-1]
33607db96d56Sopenharmony_ci
33617db96d56Sopenharmony_ci        logger = logging.getLogger("compiler.parser")
33627db96d56Sopenharmony_ci        to_send = textwrap.dedent(ConfigFileTest.config1)
33637db96d56Sopenharmony_ci        # First, specify a verification function that will fail.
33647db96d56Sopenharmony_ci        # We expect to see no output, since our configuration
33657db96d56Sopenharmony_ci        # never took effect.
33667db96d56Sopenharmony_ci        with support.captured_stdout() as output:
33677db96d56Sopenharmony_ci            self.setup_via_listener(to_send, verify_fail)
33687db96d56Sopenharmony_ci            # Both will output a message
33697db96d56Sopenharmony_ci            logger.info(self.next_message())
33707db96d56Sopenharmony_ci            logger.error(self.next_message())
33717db96d56Sopenharmony_ci        self.assert_log_lines([], stream=output)
33727db96d56Sopenharmony_ci        # Original logger output has the stuff we logged.
33737db96d56Sopenharmony_ci        self.assert_log_lines([
33747db96d56Sopenharmony_ci            ('INFO', '1'),
33757db96d56Sopenharmony_ci            ('ERROR', '2'),
33767db96d56Sopenharmony_ci        ], pat=r"^[\w.]+ -> (\w+): (\d+)$")
33777db96d56Sopenharmony_ci
33787db96d56Sopenharmony_ci        # Now, perform no verification. Our configuration
33797db96d56Sopenharmony_ci        # should take effect.
33807db96d56Sopenharmony_ci
33817db96d56Sopenharmony_ci        with support.captured_stdout() as output:
33827db96d56Sopenharmony_ci            self.setup_via_listener(to_send)    # no verify callable specified
33837db96d56Sopenharmony_ci            logger = logging.getLogger("compiler.parser")
33847db96d56Sopenharmony_ci            # Both will output a message
33857db96d56Sopenharmony_ci            logger.info(self.next_message())
33867db96d56Sopenharmony_ci            logger.error(self.next_message())
33877db96d56Sopenharmony_ci        self.assert_log_lines([
33887db96d56Sopenharmony_ci            ('INFO', '3'),
33897db96d56Sopenharmony_ci            ('ERROR', '4'),
33907db96d56Sopenharmony_ci        ], stream=output)
33917db96d56Sopenharmony_ci        # Original logger output still has the stuff we logged before.
33927db96d56Sopenharmony_ci        self.assert_log_lines([
33937db96d56Sopenharmony_ci            ('INFO', '1'),
33947db96d56Sopenharmony_ci            ('ERROR', '2'),
33957db96d56Sopenharmony_ci        ], pat=r"^[\w.]+ -> (\w+): (\d+)$")
33967db96d56Sopenharmony_ci
33977db96d56Sopenharmony_ci        # Now, perform verification which transforms the bytes.
33987db96d56Sopenharmony_ci
33997db96d56Sopenharmony_ci        with support.captured_stdout() as output:
34007db96d56Sopenharmony_ci            self.setup_via_listener(to_send[::-1], verify_reverse)
34017db96d56Sopenharmony_ci            logger = logging.getLogger("compiler.parser")
34027db96d56Sopenharmony_ci            # Both will output a message
34037db96d56Sopenharmony_ci            logger.info(self.next_message())
34047db96d56Sopenharmony_ci            logger.error(self.next_message())
34057db96d56Sopenharmony_ci        self.assert_log_lines([
34067db96d56Sopenharmony_ci            ('INFO', '5'),
34077db96d56Sopenharmony_ci            ('ERROR', '6'),
34087db96d56Sopenharmony_ci        ], stream=output)
34097db96d56Sopenharmony_ci        # Original logger output still has the stuff we logged before.
34107db96d56Sopenharmony_ci        self.assert_log_lines([
34117db96d56Sopenharmony_ci            ('INFO', '1'),
34127db96d56Sopenharmony_ci            ('ERROR', '2'),
34137db96d56Sopenharmony_ci        ], pat=r"^[\w.]+ -> (\w+): (\d+)$")
34147db96d56Sopenharmony_ci
34157db96d56Sopenharmony_ci    def test_out_of_order(self):
34167db96d56Sopenharmony_ci        self.assertRaises(ValueError, self.apply_config, self.out_of_order)
34177db96d56Sopenharmony_ci
34187db96d56Sopenharmony_ci    def test_out_of_order_with_dollar_style(self):
34197db96d56Sopenharmony_ci        config = copy.deepcopy(self.out_of_order)
34207db96d56Sopenharmony_ci        config['formatters']['mySimpleFormatter']['format'] = "${asctime} (${name}) ${levelname}: ${message}"
34217db96d56Sopenharmony_ci
34227db96d56Sopenharmony_ci        self.apply_config(config)
34237db96d56Sopenharmony_ci        handler = logging.getLogger('mymodule').handlers[0]
34247db96d56Sopenharmony_ci        self.assertIsInstance(handler.target, logging.Handler)
34257db96d56Sopenharmony_ci        self.assertIsInstance(handler.formatter._style,
34267db96d56Sopenharmony_ci                              logging.StringTemplateStyle)
34277db96d56Sopenharmony_ci
34287db96d56Sopenharmony_ci    def test_custom_formatter_class_with_validate(self):
34297db96d56Sopenharmony_ci        self.apply_config(self.custom_formatter_class_validate)
34307db96d56Sopenharmony_ci        handler = logging.getLogger("my_test_logger_custom_formatter").handlers[0]
34317db96d56Sopenharmony_ci        self.assertIsInstance(handler.formatter, ExceptionFormatter)
34327db96d56Sopenharmony_ci
34337db96d56Sopenharmony_ci    def test_custom_formatter_class_with_validate2(self):
34347db96d56Sopenharmony_ci        self.apply_config(self.custom_formatter_class_validate2)
34357db96d56Sopenharmony_ci        handler = logging.getLogger("my_test_logger_custom_formatter").handlers[0]
34367db96d56Sopenharmony_ci        self.assertIsInstance(handler.formatter, ExceptionFormatter)
34377db96d56Sopenharmony_ci
34387db96d56Sopenharmony_ci    def test_custom_formatter_class_with_validate2_with_wrong_fmt(self):
34397db96d56Sopenharmony_ci        config = self.custom_formatter_class_validate.copy()
34407db96d56Sopenharmony_ci        config['formatters']['form1']['style'] = "$"
34417db96d56Sopenharmony_ci
34427db96d56Sopenharmony_ci        # Exception should not be raise as we have configured 'validate' to False
34437db96d56Sopenharmony_ci        self.apply_config(config)
34447db96d56Sopenharmony_ci        handler = logging.getLogger("my_test_logger_custom_formatter").handlers[0]
34457db96d56Sopenharmony_ci        self.assertIsInstance(handler.formatter, ExceptionFormatter)
34467db96d56Sopenharmony_ci
34477db96d56Sopenharmony_ci    def test_custom_formatter_class_with_validate3(self):
34487db96d56Sopenharmony_ci        self.assertRaises(ValueError, self.apply_config, self.custom_formatter_class_validate3)
34497db96d56Sopenharmony_ci
34507db96d56Sopenharmony_ci    def test_custom_formatter_function_with_validate(self):
34517db96d56Sopenharmony_ci        self.assertRaises(ValueError, self.apply_config, self.custom_formatter_with_function)
34527db96d56Sopenharmony_ci
34537db96d56Sopenharmony_ci    def test_baseconfig(self):
34547db96d56Sopenharmony_ci        d = {
34557db96d56Sopenharmony_ci            'atuple': (1, 2, 3),
34567db96d56Sopenharmony_ci            'alist': ['a', 'b', 'c'],
34577db96d56Sopenharmony_ci            'adict': {'d': 'e', 'f': 3 },
34587db96d56Sopenharmony_ci            'nest1': ('g', ('h', 'i'), 'j'),
34597db96d56Sopenharmony_ci            'nest2': ['k', ['l', 'm'], 'n'],
34607db96d56Sopenharmony_ci            'nest3': ['o', 'cfg://alist', 'p'],
34617db96d56Sopenharmony_ci        }
34627db96d56Sopenharmony_ci        bc = logging.config.BaseConfigurator(d)
34637db96d56Sopenharmony_ci        self.assertEqual(bc.convert('cfg://atuple[1]'), 2)
34647db96d56Sopenharmony_ci        self.assertEqual(bc.convert('cfg://alist[1]'), 'b')
34657db96d56Sopenharmony_ci        self.assertEqual(bc.convert('cfg://nest1[1][0]'), 'h')
34667db96d56Sopenharmony_ci        self.assertEqual(bc.convert('cfg://nest2[1][1]'), 'm')
34677db96d56Sopenharmony_ci        self.assertEqual(bc.convert('cfg://adict.d'), 'e')
34687db96d56Sopenharmony_ci        self.assertEqual(bc.convert('cfg://adict[f]'), 3)
34697db96d56Sopenharmony_ci        v = bc.convert('cfg://nest3')
34707db96d56Sopenharmony_ci        self.assertEqual(v.pop(1), ['a', 'b', 'c'])
34717db96d56Sopenharmony_ci        self.assertRaises(KeyError, bc.convert, 'cfg://nosuch')
34727db96d56Sopenharmony_ci        self.assertRaises(ValueError, bc.convert, 'cfg://!')
34737db96d56Sopenharmony_ci        self.assertRaises(KeyError, bc.convert, 'cfg://adict[2]')
34747db96d56Sopenharmony_ci
34757db96d56Sopenharmony_ci    def test_namedtuple(self):
34767db96d56Sopenharmony_ci        # see bpo-39142
34777db96d56Sopenharmony_ci        from collections import namedtuple
34787db96d56Sopenharmony_ci
34797db96d56Sopenharmony_ci        class MyHandler(logging.StreamHandler):
34807db96d56Sopenharmony_ci            def __init__(self, resource, *args, **kwargs):
34817db96d56Sopenharmony_ci                super().__init__(*args, **kwargs)
34827db96d56Sopenharmony_ci                self.resource: namedtuple = resource
34837db96d56Sopenharmony_ci
34847db96d56Sopenharmony_ci            def emit(self, record):
34857db96d56Sopenharmony_ci                record.msg += f' {self.resource.type}'
34867db96d56Sopenharmony_ci                return super().emit(record)
34877db96d56Sopenharmony_ci
34887db96d56Sopenharmony_ci        Resource = namedtuple('Resource', ['type', 'labels'])
34897db96d56Sopenharmony_ci        resource = Resource(type='my_type', labels=['a'])
34907db96d56Sopenharmony_ci
34917db96d56Sopenharmony_ci        config = {
34927db96d56Sopenharmony_ci            'version': 1,
34937db96d56Sopenharmony_ci            'handlers': {
34947db96d56Sopenharmony_ci                'myhandler': {
34957db96d56Sopenharmony_ci                    '()': MyHandler,
34967db96d56Sopenharmony_ci                    'resource': resource
34977db96d56Sopenharmony_ci                }
34987db96d56Sopenharmony_ci            },
34997db96d56Sopenharmony_ci            'root':  {'level': 'INFO', 'handlers': ['myhandler']},
35007db96d56Sopenharmony_ci        }
35017db96d56Sopenharmony_ci        with support.captured_stderr() as stderr:
35027db96d56Sopenharmony_ci            self.apply_config(config)
35037db96d56Sopenharmony_ci            logging.info('some log')
35047db96d56Sopenharmony_ci        self.assertEqual(stderr.getvalue(), 'some log my_type\n')
35057db96d56Sopenharmony_ci
35067db96d56Sopenharmony_ci    def test_config_callable_filter_works(self):
35077db96d56Sopenharmony_ci        def filter_(_):
35087db96d56Sopenharmony_ci            return 1
35097db96d56Sopenharmony_ci        self.apply_config({
35107db96d56Sopenharmony_ci            "version": 1, "root": {"level": "DEBUG", "filters": [filter_]}
35117db96d56Sopenharmony_ci        })
35127db96d56Sopenharmony_ci        assert logging.getLogger().filters[0] is filter_
35137db96d56Sopenharmony_ci        logging.getLogger().filters = []
35147db96d56Sopenharmony_ci
35157db96d56Sopenharmony_ci    def test_config_filter_works(self):
35167db96d56Sopenharmony_ci        filter_ = logging.Filter("spam.eggs")
35177db96d56Sopenharmony_ci        self.apply_config({
35187db96d56Sopenharmony_ci            "version": 1, "root": {"level": "DEBUG", "filters": [filter_]}
35197db96d56Sopenharmony_ci        })
35207db96d56Sopenharmony_ci        assert logging.getLogger().filters[0] is filter_
35217db96d56Sopenharmony_ci        logging.getLogger().filters = []
35227db96d56Sopenharmony_ci
35237db96d56Sopenharmony_ci    def test_config_filter_method_works(self):
35247db96d56Sopenharmony_ci        class FakeFilter:
35257db96d56Sopenharmony_ci            def filter(self, _):
35267db96d56Sopenharmony_ci                return 1
35277db96d56Sopenharmony_ci        filter_ = FakeFilter()
35287db96d56Sopenharmony_ci        self.apply_config({
35297db96d56Sopenharmony_ci            "version": 1, "root": {"level": "DEBUG", "filters": [filter_]}
35307db96d56Sopenharmony_ci        })
35317db96d56Sopenharmony_ci        assert logging.getLogger().filters[0] is filter_
35327db96d56Sopenharmony_ci        logging.getLogger().filters = []
35337db96d56Sopenharmony_ci
35347db96d56Sopenharmony_ci    def test_invalid_type_raises(self):
35357db96d56Sopenharmony_ci        class NotAFilter: pass
35367db96d56Sopenharmony_ci        for filter_ in [None, 1, NotAFilter()]:
35377db96d56Sopenharmony_ci            self.assertRaises(
35387db96d56Sopenharmony_ci                ValueError,
35397db96d56Sopenharmony_ci                self.apply_config,
35407db96d56Sopenharmony_ci                {"version": 1, "root": {"level": "DEBUG", "filters": [filter_]}}
35417db96d56Sopenharmony_ci            )
35427db96d56Sopenharmony_ci
35437db96d56Sopenharmony_ci    def test_90195(self):
35447db96d56Sopenharmony_ci        # See gh-90195
35457db96d56Sopenharmony_ci        config = {
35467db96d56Sopenharmony_ci            'version': 1,
35477db96d56Sopenharmony_ci            'disable_existing_loggers': False,
35487db96d56Sopenharmony_ci            'handlers': {
35497db96d56Sopenharmony_ci                'console': {
35507db96d56Sopenharmony_ci                    'level': 'DEBUG',
35517db96d56Sopenharmony_ci                    'class': 'logging.StreamHandler',
35527db96d56Sopenharmony_ci                },
35537db96d56Sopenharmony_ci            },
35547db96d56Sopenharmony_ci            'loggers': {
35557db96d56Sopenharmony_ci                'a': {
35567db96d56Sopenharmony_ci                    'level': 'DEBUG',
35577db96d56Sopenharmony_ci                    'handlers': ['console']
35587db96d56Sopenharmony_ci                }
35597db96d56Sopenharmony_ci            }
35607db96d56Sopenharmony_ci        }
35617db96d56Sopenharmony_ci        logger = logging.getLogger('a')
35627db96d56Sopenharmony_ci        self.assertFalse(logger.disabled)
35637db96d56Sopenharmony_ci        self.apply_config(config)
35647db96d56Sopenharmony_ci        self.assertFalse(logger.disabled)
35657db96d56Sopenharmony_ci        # Should disable all loggers ...
35667db96d56Sopenharmony_ci        self.apply_config({'version': 1})
35677db96d56Sopenharmony_ci        self.assertTrue(logger.disabled)
35687db96d56Sopenharmony_ci        del config['disable_existing_loggers']
35697db96d56Sopenharmony_ci        self.apply_config(config)
35707db96d56Sopenharmony_ci        # Logger should be enabled, since explicitly mentioned
35717db96d56Sopenharmony_ci        self.assertFalse(logger.disabled)
35727db96d56Sopenharmony_ci
35737db96d56Sopenharmony_ciclass ManagerTest(BaseTest):
35747db96d56Sopenharmony_ci    def test_manager_loggerclass(self):
35757db96d56Sopenharmony_ci        logged = []
35767db96d56Sopenharmony_ci
35777db96d56Sopenharmony_ci        class MyLogger(logging.Logger):
35787db96d56Sopenharmony_ci            def _log(self, level, msg, args, exc_info=None, extra=None):
35797db96d56Sopenharmony_ci                logged.append(msg)
35807db96d56Sopenharmony_ci
35817db96d56Sopenharmony_ci        man = logging.Manager(None)
35827db96d56Sopenharmony_ci        self.assertRaises(TypeError, man.setLoggerClass, int)
35837db96d56Sopenharmony_ci        man.setLoggerClass(MyLogger)
35847db96d56Sopenharmony_ci        logger = man.getLogger('test')
35857db96d56Sopenharmony_ci        logger.warning('should appear in logged')
35867db96d56Sopenharmony_ci        logging.warning('should not appear in logged')
35877db96d56Sopenharmony_ci
35887db96d56Sopenharmony_ci        self.assertEqual(logged, ['should appear in logged'])
35897db96d56Sopenharmony_ci
35907db96d56Sopenharmony_ci    def test_set_log_record_factory(self):
35917db96d56Sopenharmony_ci        man = logging.Manager(None)
35927db96d56Sopenharmony_ci        expected = object()
35937db96d56Sopenharmony_ci        man.setLogRecordFactory(expected)
35947db96d56Sopenharmony_ci        self.assertEqual(man.logRecordFactory, expected)
35957db96d56Sopenharmony_ci
35967db96d56Sopenharmony_ciclass ChildLoggerTest(BaseTest):
35977db96d56Sopenharmony_ci    def test_child_loggers(self):
35987db96d56Sopenharmony_ci        r = logging.getLogger()
35997db96d56Sopenharmony_ci        l1 = logging.getLogger('abc')
36007db96d56Sopenharmony_ci        l2 = logging.getLogger('def.ghi')
36017db96d56Sopenharmony_ci        c1 = r.getChild('xyz')
36027db96d56Sopenharmony_ci        c2 = r.getChild('uvw.xyz')
36037db96d56Sopenharmony_ci        self.assertIs(c1, logging.getLogger('xyz'))
36047db96d56Sopenharmony_ci        self.assertIs(c2, logging.getLogger('uvw.xyz'))
36057db96d56Sopenharmony_ci        c1 = l1.getChild('def')
36067db96d56Sopenharmony_ci        c2 = c1.getChild('ghi')
36077db96d56Sopenharmony_ci        c3 = l1.getChild('def.ghi')
36087db96d56Sopenharmony_ci        self.assertIs(c1, logging.getLogger('abc.def'))
36097db96d56Sopenharmony_ci        self.assertIs(c2, logging.getLogger('abc.def.ghi'))
36107db96d56Sopenharmony_ci        self.assertIs(c2, c3)
36117db96d56Sopenharmony_ci
36127db96d56Sopenharmony_ci
36137db96d56Sopenharmony_ciclass DerivedLogRecord(logging.LogRecord):
36147db96d56Sopenharmony_ci    pass
36157db96d56Sopenharmony_ci
36167db96d56Sopenharmony_ciclass LogRecordFactoryTest(BaseTest):
36177db96d56Sopenharmony_ci
36187db96d56Sopenharmony_ci    def setUp(self):
36197db96d56Sopenharmony_ci        class CheckingFilter(logging.Filter):
36207db96d56Sopenharmony_ci            def __init__(self, cls):
36217db96d56Sopenharmony_ci                self.cls = cls
36227db96d56Sopenharmony_ci
36237db96d56Sopenharmony_ci            def filter(self, record):
36247db96d56Sopenharmony_ci                t = type(record)
36257db96d56Sopenharmony_ci                if t is not self.cls:
36267db96d56Sopenharmony_ci                    msg = 'Unexpected LogRecord type %s, expected %s' % (t,
36277db96d56Sopenharmony_ci                            self.cls)
36287db96d56Sopenharmony_ci                    raise TypeError(msg)
36297db96d56Sopenharmony_ci                return True
36307db96d56Sopenharmony_ci
36317db96d56Sopenharmony_ci        BaseTest.setUp(self)
36327db96d56Sopenharmony_ci        self.filter = CheckingFilter(DerivedLogRecord)
36337db96d56Sopenharmony_ci        self.root_logger.addFilter(self.filter)
36347db96d56Sopenharmony_ci        self.orig_factory = logging.getLogRecordFactory()
36357db96d56Sopenharmony_ci
36367db96d56Sopenharmony_ci    def tearDown(self):
36377db96d56Sopenharmony_ci        self.root_logger.removeFilter(self.filter)
36387db96d56Sopenharmony_ci        BaseTest.tearDown(self)
36397db96d56Sopenharmony_ci        logging.setLogRecordFactory(self.orig_factory)
36407db96d56Sopenharmony_ci
36417db96d56Sopenharmony_ci    def test_logrecord_class(self):
36427db96d56Sopenharmony_ci        self.assertRaises(TypeError, self.root_logger.warning,
36437db96d56Sopenharmony_ci                          self.next_message())
36447db96d56Sopenharmony_ci        logging.setLogRecordFactory(DerivedLogRecord)
36457db96d56Sopenharmony_ci        self.root_logger.error(self.next_message())
36467db96d56Sopenharmony_ci        self.assert_log_lines([
36477db96d56Sopenharmony_ci           ('root', 'ERROR', '2'),
36487db96d56Sopenharmony_ci        ])
36497db96d56Sopenharmony_ci
36507db96d56Sopenharmony_ci
36517db96d56Sopenharmony_ci@threading_helper.requires_working_threading()
36527db96d56Sopenharmony_ciclass QueueHandlerTest(BaseTest):
36537db96d56Sopenharmony_ci    # Do not bother with a logger name group.
36547db96d56Sopenharmony_ci    expected_log_pat = r"^[\w.]+ -> (\w+): (\d+)$"
36557db96d56Sopenharmony_ci
36567db96d56Sopenharmony_ci    def setUp(self):
36577db96d56Sopenharmony_ci        BaseTest.setUp(self)
36587db96d56Sopenharmony_ci        self.queue = queue.Queue(-1)
36597db96d56Sopenharmony_ci        self.que_hdlr = logging.handlers.QueueHandler(self.queue)
36607db96d56Sopenharmony_ci        self.name = 'que'
36617db96d56Sopenharmony_ci        self.que_logger = logging.getLogger('que')
36627db96d56Sopenharmony_ci        self.que_logger.propagate = False
36637db96d56Sopenharmony_ci        self.que_logger.setLevel(logging.WARNING)
36647db96d56Sopenharmony_ci        self.que_logger.addHandler(self.que_hdlr)
36657db96d56Sopenharmony_ci
36667db96d56Sopenharmony_ci    def tearDown(self):
36677db96d56Sopenharmony_ci        self.que_hdlr.close()
36687db96d56Sopenharmony_ci        BaseTest.tearDown(self)
36697db96d56Sopenharmony_ci
36707db96d56Sopenharmony_ci    def test_queue_handler(self):
36717db96d56Sopenharmony_ci        self.que_logger.debug(self.next_message())
36727db96d56Sopenharmony_ci        self.assertRaises(queue.Empty, self.queue.get_nowait)
36737db96d56Sopenharmony_ci        self.que_logger.info(self.next_message())
36747db96d56Sopenharmony_ci        self.assertRaises(queue.Empty, self.queue.get_nowait)
36757db96d56Sopenharmony_ci        msg = self.next_message()
36767db96d56Sopenharmony_ci        self.que_logger.warning(msg)
36777db96d56Sopenharmony_ci        data = self.queue.get_nowait()
36787db96d56Sopenharmony_ci        self.assertTrue(isinstance(data, logging.LogRecord))
36797db96d56Sopenharmony_ci        self.assertEqual(data.name, self.que_logger.name)
36807db96d56Sopenharmony_ci        self.assertEqual((data.msg, data.args), (msg, None))
36817db96d56Sopenharmony_ci
36827db96d56Sopenharmony_ci    def test_formatting(self):
36837db96d56Sopenharmony_ci        msg = self.next_message()
36847db96d56Sopenharmony_ci        levelname = logging.getLevelName(logging.WARNING)
36857db96d56Sopenharmony_ci        log_format_str = '{name} -> {levelname}: {message}'
36867db96d56Sopenharmony_ci        formatted_msg = log_format_str.format(name=self.name,
36877db96d56Sopenharmony_ci                                              levelname=levelname, message=msg)
36887db96d56Sopenharmony_ci        formatter = logging.Formatter(self.log_format)
36897db96d56Sopenharmony_ci        self.que_hdlr.setFormatter(formatter)
36907db96d56Sopenharmony_ci        self.que_logger.warning(msg)
36917db96d56Sopenharmony_ci        log_record = self.queue.get_nowait()
36927db96d56Sopenharmony_ci        self.assertEqual(formatted_msg, log_record.msg)
36937db96d56Sopenharmony_ci        self.assertEqual(formatted_msg, log_record.message)
36947db96d56Sopenharmony_ci
36957db96d56Sopenharmony_ci    @unittest.skipUnless(hasattr(logging.handlers, 'QueueListener'),
36967db96d56Sopenharmony_ci                         'logging.handlers.QueueListener required for this test')
36977db96d56Sopenharmony_ci    def test_queue_listener(self):
36987db96d56Sopenharmony_ci        handler = TestHandler(support.Matcher())
36997db96d56Sopenharmony_ci        listener = logging.handlers.QueueListener(self.queue, handler)
37007db96d56Sopenharmony_ci        listener.start()
37017db96d56Sopenharmony_ci        try:
37027db96d56Sopenharmony_ci            self.que_logger.warning(self.next_message())
37037db96d56Sopenharmony_ci            self.que_logger.error(self.next_message())
37047db96d56Sopenharmony_ci            self.que_logger.critical(self.next_message())
37057db96d56Sopenharmony_ci        finally:
37067db96d56Sopenharmony_ci            listener.stop()
37077db96d56Sopenharmony_ci        self.assertTrue(handler.matches(levelno=logging.WARNING, message='1'))
37087db96d56Sopenharmony_ci        self.assertTrue(handler.matches(levelno=logging.ERROR, message='2'))
37097db96d56Sopenharmony_ci        self.assertTrue(handler.matches(levelno=logging.CRITICAL, message='3'))
37107db96d56Sopenharmony_ci        handler.close()
37117db96d56Sopenharmony_ci
37127db96d56Sopenharmony_ci        # Now test with respect_handler_level set
37137db96d56Sopenharmony_ci
37147db96d56Sopenharmony_ci        handler = TestHandler(support.Matcher())
37157db96d56Sopenharmony_ci        handler.setLevel(logging.CRITICAL)
37167db96d56Sopenharmony_ci        listener = logging.handlers.QueueListener(self.queue, handler,
37177db96d56Sopenharmony_ci                                                  respect_handler_level=True)
37187db96d56Sopenharmony_ci        listener.start()
37197db96d56Sopenharmony_ci        try:
37207db96d56Sopenharmony_ci            self.que_logger.warning(self.next_message())
37217db96d56Sopenharmony_ci            self.que_logger.error(self.next_message())
37227db96d56Sopenharmony_ci            self.que_logger.critical(self.next_message())
37237db96d56Sopenharmony_ci        finally:
37247db96d56Sopenharmony_ci            listener.stop()
37257db96d56Sopenharmony_ci        self.assertFalse(handler.matches(levelno=logging.WARNING, message='4'))
37267db96d56Sopenharmony_ci        self.assertFalse(handler.matches(levelno=logging.ERROR, message='5'))
37277db96d56Sopenharmony_ci        self.assertTrue(handler.matches(levelno=logging.CRITICAL, message='6'))
37287db96d56Sopenharmony_ci        handler.close()
37297db96d56Sopenharmony_ci
37307db96d56Sopenharmony_ci    @unittest.skipUnless(hasattr(logging.handlers, 'QueueListener'),
37317db96d56Sopenharmony_ci                         'logging.handlers.QueueListener required for this test')
37327db96d56Sopenharmony_ci    def test_queue_listener_with_StreamHandler(self):
37337db96d56Sopenharmony_ci        # Test that traceback and stack-info only appends once (bpo-34334, bpo-46755).
37347db96d56Sopenharmony_ci        listener = logging.handlers.QueueListener(self.queue, self.root_hdlr)
37357db96d56Sopenharmony_ci        listener.start()
37367db96d56Sopenharmony_ci        try:
37377db96d56Sopenharmony_ci            1 / 0
37387db96d56Sopenharmony_ci        except ZeroDivisionError as e:
37397db96d56Sopenharmony_ci            exc = e
37407db96d56Sopenharmony_ci            self.que_logger.exception(self.next_message(), exc_info=exc)
37417db96d56Sopenharmony_ci        self.que_logger.error(self.next_message(), stack_info=True)
37427db96d56Sopenharmony_ci        listener.stop()
37437db96d56Sopenharmony_ci        self.assertEqual(self.stream.getvalue().strip().count('Traceback'), 1)
37447db96d56Sopenharmony_ci        self.assertEqual(self.stream.getvalue().strip().count('Stack'), 1)
37457db96d56Sopenharmony_ci
37467db96d56Sopenharmony_ci    @unittest.skipUnless(hasattr(logging.handlers, 'QueueListener'),
37477db96d56Sopenharmony_ci                         'logging.handlers.QueueListener required for this test')
37487db96d56Sopenharmony_ci    def test_queue_listener_with_multiple_handlers(self):
37497db96d56Sopenharmony_ci        # Test that queue handler format doesn't affect other handler formats (bpo-35726).
37507db96d56Sopenharmony_ci        self.que_hdlr.setFormatter(self.root_formatter)
37517db96d56Sopenharmony_ci        self.que_logger.addHandler(self.root_hdlr)
37527db96d56Sopenharmony_ci
37537db96d56Sopenharmony_ci        listener = logging.handlers.QueueListener(self.queue, self.que_hdlr)
37547db96d56Sopenharmony_ci        listener.start()
37557db96d56Sopenharmony_ci        self.que_logger.error("error")
37567db96d56Sopenharmony_ci        listener.stop()
37577db96d56Sopenharmony_ci        self.assertEqual(self.stream.getvalue().strip(), "que -> ERROR: error")
37587db96d56Sopenharmony_ci
37597db96d56Sopenharmony_ciif hasattr(logging.handlers, 'QueueListener'):
37607db96d56Sopenharmony_ci    import multiprocessing
37617db96d56Sopenharmony_ci    from unittest.mock import patch
37627db96d56Sopenharmony_ci
37637db96d56Sopenharmony_ci    @threading_helper.requires_working_threading()
37647db96d56Sopenharmony_ci    class QueueListenerTest(BaseTest):
37657db96d56Sopenharmony_ci        """
37667db96d56Sopenharmony_ci        Tests based on patch submitted for issue #27930. Ensure that
37677db96d56Sopenharmony_ci        QueueListener handles all log messages.
37687db96d56Sopenharmony_ci        """
37697db96d56Sopenharmony_ci
37707db96d56Sopenharmony_ci        repeat = 20
37717db96d56Sopenharmony_ci
37727db96d56Sopenharmony_ci        @staticmethod
37737db96d56Sopenharmony_ci        def setup_and_log(log_queue, ident):
37747db96d56Sopenharmony_ci            """
37757db96d56Sopenharmony_ci            Creates a logger with a QueueHandler that logs to a queue read by a
37767db96d56Sopenharmony_ci            QueueListener. Starts the listener, logs five messages, and stops
37777db96d56Sopenharmony_ci            the listener.
37787db96d56Sopenharmony_ci            """
37797db96d56Sopenharmony_ci            logger = logging.getLogger('test_logger_with_id_%s' % ident)
37807db96d56Sopenharmony_ci            logger.setLevel(logging.DEBUG)
37817db96d56Sopenharmony_ci            handler = logging.handlers.QueueHandler(log_queue)
37827db96d56Sopenharmony_ci            logger.addHandler(handler)
37837db96d56Sopenharmony_ci            listener = logging.handlers.QueueListener(log_queue)
37847db96d56Sopenharmony_ci            listener.start()
37857db96d56Sopenharmony_ci
37867db96d56Sopenharmony_ci            logger.info('one')
37877db96d56Sopenharmony_ci            logger.info('two')
37887db96d56Sopenharmony_ci            logger.info('three')
37897db96d56Sopenharmony_ci            logger.info('four')
37907db96d56Sopenharmony_ci            logger.info('five')
37917db96d56Sopenharmony_ci
37927db96d56Sopenharmony_ci            listener.stop()
37937db96d56Sopenharmony_ci            logger.removeHandler(handler)
37947db96d56Sopenharmony_ci            handler.close()
37957db96d56Sopenharmony_ci
37967db96d56Sopenharmony_ci        @patch.object(logging.handlers.QueueListener, 'handle')
37977db96d56Sopenharmony_ci        def test_handle_called_with_queue_queue(self, mock_handle):
37987db96d56Sopenharmony_ci            for i in range(self.repeat):
37997db96d56Sopenharmony_ci                log_queue = queue.Queue()
38007db96d56Sopenharmony_ci                self.setup_and_log(log_queue, '%s_%s' % (self.id(), i))
38017db96d56Sopenharmony_ci            self.assertEqual(mock_handle.call_count, 5 * self.repeat,
38027db96d56Sopenharmony_ci                             'correct number of handled log messages')
38037db96d56Sopenharmony_ci
38047db96d56Sopenharmony_ci        @patch.object(logging.handlers.QueueListener, 'handle')
38057db96d56Sopenharmony_ci        def test_handle_called_with_mp_queue(self, mock_handle):
38067db96d56Sopenharmony_ci            # bpo-28668: The multiprocessing (mp) module is not functional
38077db96d56Sopenharmony_ci            # when the mp.synchronize module cannot be imported.
38087db96d56Sopenharmony_ci            support.skip_if_broken_multiprocessing_synchronize()
38097db96d56Sopenharmony_ci            for i in range(self.repeat):
38107db96d56Sopenharmony_ci                log_queue = multiprocessing.Queue()
38117db96d56Sopenharmony_ci                self.setup_and_log(log_queue, '%s_%s' % (self.id(), i))
38127db96d56Sopenharmony_ci                log_queue.close()
38137db96d56Sopenharmony_ci                log_queue.join_thread()
38147db96d56Sopenharmony_ci            self.assertEqual(mock_handle.call_count, 5 * self.repeat,
38157db96d56Sopenharmony_ci                             'correct number of handled log messages')
38167db96d56Sopenharmony_ci
38177db96d56Sopenharmony_ci        @staticmethod
38187db96d56Sopenharmony_ci        def get_all_from_queue(log_queue):
38197db96d56Sopenharmony_ci            try:
38207db96d56Sopenharmony_ci                while True:
38217db96d56Sopenharmony_ci                    yield log_queue.get_nowait()
38227db96d56Sopenharmony_ci            except queue.Empty:
38237db96d56Sopenharmony_ci                return []
38247db96d56Sopenharmony_ci
38257db96d56Sopenharmony_ci        def test_no_messages_in_queue_after_stop(self):
38267db96d56Sopenharmony_ci            """
38277db96d56Sopenharmony_ci            Five messages are logged then the QueueListener is stopped. This
38287db96d56Sopenharmony_ci            test then gets everything off the queue. Failure of this test
38297db96d56Sopenharmony_ci            indicates that messages were not registered on the queue until
38307db96d56Sopenharmony_ci            _after_ the QueueListener stopped.
38317db96d56Sopenharmony_ci            """
38327db96d56Sopenharmony_ci            # bpo-28668: The multiprocessing (mp) module is not functional
38337db96d56Sopenharmony_ci            # when the mp.synchronize module cannot be imported.
38347db96d56Sopenharmony_ci            support.skip_if_broken_multiprocessing_synchronize()
38357db96d56Sopenharmony_ci            for i in range(self.repeat):
38367db96d56Sopenharmony_ci                queue = multiprocessing.Queue()
38377db96d56Sopenharmony_ci                self.setup_and_log(queue, '%s_%s' %(self.id(), i))
38387db96d56Sopenharmony_ci                # time.sleep(1)
38397db96d56Sopenharmony_ci                items = list(self.get_all_from_queue(queue))
38407db96d56Sopenharmony_ci                queue.close()
38417db96d56Sopenharmony_ci                queue.join_thread()
38427db96d56Sopenharmony_ci
38437db96d56Sopenharmony_ci                expected = [[], [logging.handlers.QueueListener._sentinel]]
38447db96d56Sopenharmony_ci                self.assertIn(items, expected,
38457db96d56Sopenharmony_ci                              'Found unexpected messages in queue: %s' % (
38467db96d56Sopenharmony_ci                                    [m.msg if isinstance(m, logging.LogRecord)
38477db96d56Sopenharmony_ci                                     else m for m in items]))
38487db96d56Sopenharmony_ci
38497db96d56Sopenharmony_ci        def test_calls_task_done_after_stop(self):
38507db96d56Sopenharmony_ci            # Issue 36813: Make sure queue.join does not deadlock.
38517db96d56Sopenharmony_ci            log_queue = queue.Queue()
38527db96d56Sopenharmony_ci            listener = logging.handlers.QueueListener(log_queue)
38537db96d56Sopenharmony_ci            listener.start()
38547db96d56Sopenharmony_ci            listener.stop()
38557db96d56Sopenharmony_ci            with self.assertRaises(ValueError):
38567db96d56Sopenharmony_ci                # Make sure all tasks are done and .join won't block.
38577db96d56Sopenharmony_ci                log_queue.task_done()
38587db96d56Sopenharmony_ci
38597db96d56Sopenharmony_ci
38607db96d56Sopenharmony_ciZERO = datetime.timedelta(0)
38617db96d56Sopenharmony_ci
38627db96d56Sopenharmony_ciclass UTC(datetime.tzinfo):
38637db96d56Sopenharmony_ci    def utcoffset(self, dt):
38647db96d56Sopenharmony_ci        return ZERO
38657db96d56Sopenharmony_ci
38667db96d56Sopenharmony_ci    dst = utcoffset
38677db96d56Sopenharmony_ci
38687db96d56Sopenharmony_ci    def tzname(self, dt):
38697db96d56Sopenharmony_ci        return 'UTC'
38707db96d56Sopenharmony_ci
38717db96d56Sopenharmony_ciutc = UTC()
38727db96d56Sopenharmony_ci
38737db96d56Sopenharmony_ciclass AssertErrorMessage:
38747db96d56Sopenharmony_ci
38757db96d56Sopenharmony_ci    def assert_error_message(self, exception, message, *args, **kwargs):
38767db96d56Sopenharmony_ci        try:
38777db96d56Sopenharmony_ci            self.assertRaises((), *args, **kwargs)
38787db96d56Sopenharmony_ci        except exception as e:
38797db96d56Sopenharmony_ci            self.assertEqual(message, str(e))
38807db96d56Sopenharmony_ci
38817db96d56Sopenharmony_ciclass FormatterTest(unittest.TestCase, AssertErrorMessage):
38827db96d56Sopenharmony_ci    def setUp(self):
38837db96d56Sopenharmony_ci        self.common = {
38847db96d56Sopenharmony_ci            'name': 'formatter.test',
38857db96d56Sopenharmony_ci            'level': logging.DEBUG,
38867db96d56Sopenharmony_ci            'pathname': os.path.join('path', 'to', 'dummy.ext'),
38877db96d56Sopenharmony_ci            'lineno': 42,
38887db96d56Sopenharmony_ci            'exc_info': None,
38897db96d56Sopenharmony_ci            'func': None,
38907db96d56Sopenharmony_ci            'msg': 'Message with %d %s',
38917db96d56Sopenharmony_ci            'args': (2, 'placeholders'),
38927db96d56Sopenharmony_ci        }
38937db96d56Sopenharmony_ci        self.variants = {
38947db96d56Sopenharmony_ci            'custom': {
38957db96d56Sopenharmony_ci                'custom': 1234
38967db96d56Sopenharmony_ci            }
38977db96d56Sopenharmony_ci        }
38987db96d56Sopenharmony_ci
38997db96d56Sopenharmony_ci    def get_record(self, name=None):
39007db96d56Sopenharmony_ci        result = dict(self.common)
39017db96d56Sopenharmony_ci        if name is not None:
39027db96d56Sopenharmony_ci            result.update(self.variants[name])
39037db96d56Sopenharmony_ci        return logging.makeLogRecord(result)
39047db96d56Sopenharmony_ci
39057db96d56Sopenharmony_ci    def test_percent(self):
39067db96d56Sopenharmony_ci        # Test %-formatting
39077db96d56Sopenharmony_ci        r = self.get_record()
39087db96d56Sopenharmony_ci        f = logging.Formatter('${%(message)s}')
39097db96d56Sopenharmony_ci        self.assertEqual(f.format(r), '${Message with 2 placeholders}')
39107db96d56Sopenharmony_ci        f = logging.Formatter('%(random)s')
39117db96d56Sopenharmony_ci        self.assertRaises(ValueError, f.format, r)
39127db96d56Sopenharmony_ci        self.assertFalse(f.usesTime())
39137db96d56Sopenharmony_ci        f = logging.Formatter('%(asctime)s')
39147db96d56Sopenharmony_ci        self.assertTrue(f.usesTime())
39157db96d56Sopenharmony_ci        f = logging.Formatter('%(asctime)-15s')
39167db96d56Sopenharmony_ci        self.assertTrue(f.usesTime())
39177db96d56Sopenharmony_ci        f = logging.Formatter('%(asctime)#15s')
39187db96d56Sopenharmony_ci        self.assertTrue(f.usesTime())
39197db96d56Sopenharmony_ci
39207db96d56Sopenharmony_ci    def test_braces(self):
39217db96d56Sopenharmony_ci        # Test {}-formatting
39227db96d56Sopenharmony_ci        r = self.get_record()
39237db96d56Sopenharmony_ci        f = logging.Formatter('$%{message}%$', style='{')
39247db96d56Sopenharmony_ci        self.assertEqual(f.format(r), '$%Message with 2 placeholders%$')
39257db96d56Sopenharmony_ci        f = logging.Formatter('{random}', style='{')
39267db96d56Sopenharmony_ci        self.assertRaises(ValueError, f.format, r)
39277db96d56Sopenharmony_ci        f = logging.Formatter("{message}", style='{')
39287db96d56Sopenharmony_ci        self.assertFalse(f.usesTime())
39297db96d56Sopenharmony_ci        f = logging.Formatter('{asctime}', style='{')
39307db96d56Sopenharmony_ci        self.assertTrue(f.usesTime())
39317db96d56Sopenharmony_ci        f = logging.Formatter('{asctime!s:15}', style='{')
39327db96d56Sopenharmony_ci        self.assertTrue(f.usesTime())
39337db96d56Sopenharmony_ci        f = logging.Formatter('{asctime:15}', style='{')
39347db96d56Sopenharmony_ci        self.assertTrue(f.usesTime())
39357db96d56Sopenharmony_ci
39367db96d56Sopenharmony_ci    def test_dollars(self):
39377db96d56Sopenharmony_ci        # Test $-formatting
39387db96d56Sopenharmony_ci        r = self.get_record()
39397db96d56Sopenharmony_ci        f = logging.Formatter('${message}', style='$')
39407db96d56Sopenharmony_ci        self.assertEqual(f.format(r), 'Message with 2 placeholders')
39417db96d56Sopenharmony_ci        f = logging.Formatter('$message', style='$')
39427db96d56Sopenharmony_ci        self.assertEqual(f.format(r), 'Message with 2 placeholders')
39437db96d56Sopenharmony_ci        f = logging.Formatter('$$%${message}%$$', style='$')
39447db96d56Sopenharmony_ci        self.assertEqual(f.format(r), '$%Message with 2 placeholders%$')
39457db96d56Sopenharmony_ci        f = logging.Formatter('${random}', style='$')
39467db96d56Sopenharmony_ci        self.assertRaises(ValueError, f.format, r)
39477db96d56Sopenharmony_ci        self.assertFalse(f.usesTime())
39487db96d56Sopenharmony_ci        f = logging.Formatter('${asctime}', style='$')
39497db96d56Sopenharmony_ci        self.assertTrue(f.usesTime())
39507db96d56Sopenharmony_ci        f = logging.Formatter('$asctime', style='$')
39517db96d56Sopenharmony_ci        self.assertTrue(f.usesTime())
39527db96d56Sopenharmony_ci        f = logging.Formatter('${message}', style='$')
39537db96d56Sopenharmony_ci        self.assertFalse(f.usesTime())
39547db96d56Sopenharmony_ci        f = logging.Formatter('${asctime}--', style='$')
39557db96d56Sopenharmony_ci        self.assertTrue(f.usesTime())
39567db96d56Sopenharmony_ci
39577db96d56Sopenharmony_ci    def test_format_validate(self):
39587db96d56Sopenharmony_ci        # Check correct formatting
39597db96d56Sopenharmony_ci        # Percentage style
39607db96d56Sopenharmony_ci        f = logging.Formatter("%(levelname)-15s - %(message) 5s - %(process)03d - %(module) - %(asctime)*.3s")
39617db96d56Sopenharmony_ci        self.assertEqual(f._fmt, "%(levelname)-15s - %(message) 5s - %(process)03d - %(module) - %(asctime)*.3s")
39627db96d56Sopenharmony_ci        f = logging.Formatter("%(asctime)*s - %(asctime)*.3s - %(process)-34.33o")
39637db96d56Sopenharmony_ci        self.assertEqual(f._fmt, "%(asctime)*s - %(asctime)*.3s - %(process)-34.33o")
39647db96d56Sopenharmony_ci        f = logging.Formatter("%(process)#+027.23X")
39657db96d56Sopenharmony_ci        self.assertEqual(f._fmt, "%(process)#+027.23X")
39667db96d56Sopenharmony_ci        f = logging.Formatter("%(foo)#.*g")
39677db96d56Sopenharmony_ci        self.assertEqual(f._fmt, "%(foo)#.*g")
39687db96d56Sopenharmony_ci
39697db96d56Sopenharmony_ci        # StrFormat Style
39707db96d56Sopenharmony_ci        f = logging.Formatter("$%{message}%$ - {asctime!a:15} - {customfield['key']}", style="{")
39717db96d56Sopenharmony_ci        self.assertEqual(f._fmt, "$%{message}%$ - {asctime!a:15} - {customfield['key']}")
39727db96d56Sopenharmony_ci        f = logging.Formatter("{process:.2f} - {custom.f:.4f}", style="{")
39737db96d56Sopenharmony_ci        self.assertEqual(f._fmt, "{process:.2f} - {custom.f:.4f}")
39747db96d56Sopenharmony_ci        f = logging.Formatter("{customfield!s:#<30}", style="{")
39757db96d56Sopenharmony_ci        self.assertEqual(f._fmt, "{customfield!s:#<30}")
39767db96d56Sopenharmony_ci        f = logging.Formatter("{message!r}", style="{")
39777db96d56Sopenharmony_ci        self.assertEqual(f._fmt, "{message!r}")
39787db96d56Sopenharmony_ci        f = logging.Formatter("{message!s}", style="{")
39797db96d56Sopenharmony_ci        self.assertEqual(f._fmt, "{message!s}")
39807db96d56Sopenharmony_ci        f = logging.Formatter("{message!a}", style="{")
39817db96d56Sopenharmony_ci        self.assertEqual(f._fmt, "{message!a}")
39827db96d56Sopenharmony_ci        f = logging.Formatter("{process!r:4.2}", style="{")
39837db96d56Sopenharmony_ci        self.assertEqual(f._fmt, "{process!r:4.2}")
39847db96d56Sopenharmony_ci        f = logging.Formatter("{process!s:<#30,.12f}- {custom:=+#30,.1d} - {module:^30}", style="{")
39857db96d56Sopenharmony_ci        self.assertEqual(f._fmt, "{process!s:<#30,.12f}- {custom:=+#30,.1d} - {module:^30}")
39867db96d56Sopenharmony_ci        f = logging.Formatter("{process!s:{w},.{p}}", style="{")
39877db96d56Sopenharmony_ci        self.assertEqual(f._fmt, "{process!s:{w},.{p}}")
39887db96d56Sopenharmony_ci        f = logging.Formatter("{foo:12.{p}}", style="{")
39897db96d56Sopenharmony_ci        self.assertEqual(f._fmt, "{foo:12.{p}}")
39907db96d56Sopenharmony_ci        f = logging.Formatter("{foo:{w}.6}", style="{")
39917db96d56Sopenharmony_ci        self.assertEqual(f._fmt, "{foo:{w}.6}")
39927db96d56Sopenharmony_ci        f = logging.Formatter("{foo[0].bar[1].baz}", style="{")
39937db96d56Sopenharmony_ci        self.assertEqual(f._fmt, "{foo[0].bar[1].baz}")
39947db96d56Sopenharmony_ci        f = logging.Formatter("{foo[k1].bar[k2].baz}", style="{")
39957db96d56Sopenharmony_ci        self.assertEqual(f._fmt, "{foo[k1].bar[k2].baz}")
39967db96d56Sopenharmony_ci        f = logging.Formatter("{12[k1].bar[k2].baz}", style="{")
39977db96d56Sopenharmony_ci        self.assertEqual(f._fmt, "{12[k1].bar[k2].baz}")
39987db96d56Sopenharmony_ci
39997db96d56Sopenharmony_ci        # Dollar style
40007db96d56Sopenharmony_ci        f = logging.Formatter("${asctime} - $message", style="$")
40017db96d56Sopenharmony_ci        self.assertEqual(f._fmt, "${asctime} - $message")
40027db96d56Sopenharmony_ci        f = logging.Formatter("$bar $$", style="$")
40037db96d56Sopenharmony_ci        self.assertEqual(f._fmt, "$bar $$")
40047db96d56Sopenharmony_ci        f = logging.Formatter("$bar $$$$", style="$")
40057db96d56Sopenharmony_ci        self.assertEqual(f._fmt, "$bar $$$$")  # this would print two $($$)
40067db96d56Sopenharmony_ci
40077db96d56Sopenharmony_ci        # Testing when ValueError being raised from incorrect format
40087db96d56Sopenharmony_ci        # Percentage Style
40097db96d56Sopenharmony_ci        self.assertRaises(ValueError, logging.Formatter, "%(asctime)Z")
40107db96d56Sopenharmony_ci        self.assertRaises(ValueError, logging.Formatter, "%(asctime)b")
40117db96d56Sopenharmony_ci        self.assertRaises(ValueError, logging.Formatter, "%(asctime)*")
40127db96d56Sopenharmony_ci        self.assertRaises(ValueError, logging.Formatter, "%(asctime)*3s")
40137db96d56Sopenharmony_ci        self.assertRaises(ValueError, logging.Formatter, "%(asctime)_")
40147db96d56Sopenharmony_ci        self.assertRaises(ValueError, logging.Formatter, '{asctime}')
40157db96d56Sopenharmony_ci        self.assertRaises(ValueError, logging.Formatter, '${message}')
40167db96d56Sopenharmony_ci        self.assertRaises(ValueError, logging.Formatter, '%(foo)#12.3*f')  # with both * and decimal number as precision
40177db96d56Sopenharmony_ci        self.assertRaises(ValueError, logging.Formatter, '%(foo)0*.8*f')
40187db96d56Sopenharmony_ci
40197db96d56Sopenharmony_ci        # StrFormat Style
40207db96d56Sopenharmony_ci        # Testing failure for '-' in field name
40217db96d56Sopenharmony_ci        self.assert_error_message(
40227db96d56Sopenharmony_ci            ValueError,
40237db96d56Sopenharmony_ci            "invalid format: invalid field name/expression: 'name-thing'",
40247db96d56Sopenharmony_ci            logging.Formatter, "{name-thing}", style="{"
40257db96d56Sopenharmony_ci        )
40267db96d56Sopenharmony_ci        # Testing failure for style mismatch
40277db96d56Sopenharmony_ci        self.assert_error_message(
40287db96d56Sopenharmony_ci            ValueError,
40297db96d56Sopenharmony_ci            "invalid format: no fields",
40307db96d56Sopenharmony_ci            logging.Formatter, '%(asctime)s', style='{'
40317db96d56Sopenharmony_ci        )
40327db96d56Sopenharmony_ci        # Testing failure for invalid conversion
40337db96d56Sopenharmony_ci        self.assert_error_message(
40347db96d56Sopenharmony_ci            ValueError,
40357db96d56Sopenharmony_ci            "invalid conversion: 'Z'"
40367db96d56Sopenharmony_ci        )
40377db96d56Sopenharmony_ci        self.assertRaises(ValueError, logging.Formatter, '{asctime!s:#30,15f}', style='{')
40387db96d56Sopenharmony_ci        self.assert_error_message(
40397db96d56Sopenharmony_ci            ValueError,
40407db96d56Sopenharmony_ci            "invalid format: expected ':' after conversion specifier",
40417db96d56Sopenharmony_ci            logging.Formatter, '{asctime!aa:15}', style='{'
40427db96d56Sopenharmony_ci        )
40437db96d56Sopenharmony_ci        # Testing failure for invalid spec
40447db96d56Sopenharmony_ci        self.assert_error_message(
40457db96d56Sopenharmony_ci            ValueError,
40467db96d56Sopenharmony_ci            "invalid format: bad specifier: '.2ff'",
40477db96d56Sopenharmony_ci            logging.Formatter, '{process:.2ff}', style='{'
40487db96d56Sopenharmony_ci        )
40497db96d56Sopenharmony_ci        self.assertRaises(ValueError, logging.Formatter, '{process:.2Z}', style='{')
40507db96d56Sopenharmony_ci        self.assertRaises(ValueError, logging.Formatter, '{process!s:<##30,12g}', style='{')
40517db96d56Sopenharmony_ci        self.assertRaises(ValueError, logging.Formatter, '{process!s:<#30#,12g}', style='{')
40527db96d56Sopenharmony_ci        self.assertRaises(ValueError, logging.Formatter, '{process!s:{{w}},{{p}}}', style='{')
40537db96d56Sopenharmony_ci        # Testing failure for mismatch braces
40547db96d56Sopenharmony_ci        self.assert_error_message(
40557db96d56Sopenharmony_ci            ValueError,
40567db96d56Sopenharmony_ci            "invalid format: expected '}' before end of string",
40577db96d56Sopenharmony_ci            logging.Formatter, '{process', style='{'
40587db96d56Sopenharmony_ci        )
40597db96d56Sopenharmony_ci        self.assert_error_message(
40607db96d56Sopenharmony_ci            ValueError,
40617db96d56Sopenharmony_ci            "invalid format: Single '}' encountered in format string",
40627db96d56Sopenharmony_ci            logging.Formatter, 'process}', style='{'
40637db96d56Sopenharmony_ci        )
40647db96d56Sopenharmony_ci        self.assertRaises(ValueError, logging.Formatter, '{{foo!r:4.2}', style='{')
40657db96d56Sopenharmony_ci        self.assertRaises(ValueError, logging.Formatter, '{{foo!r:4.2}}', style='{')
40667db96d56Sopenharmony_ci        self.assertRaises(ValueError, logging.Formatter, '{foo/bar}', style='{')
40677db96d56Sopenharmony_ci        self.assertRaises(ValueError, logging.Formatter, '{foo:{{w}}.{{p}}}}', style='{')
40687db96d56Sopenharmony_ci        self.assertRaises(ValueError, logging.Formatter, '{foo!X:{{w}}.{{p}}}', style='{')
40697db96d56Sopenharmony_ci        self.assertRaises(ValueError, logging.Formatter, '{foo!a:random}', style='{')
40707db96d56Sopenharmony_ci        self.assertRaises(ValueError, logging.Formatter, '{foo!a:ran{dom}', style='{')
40717db96d56Sopenharmony_ci        self.assertRaises(ValueError, logging.Formatter, '{foo!a:ran{d}om}', style='{')
40727db96d56Sopenharmony_ci        self.assertRaises(ValueError, logging.Formatter, '{foo.!a:d}', style='{')
40737db96d56Sopenharmony_ci
40747db96d56Sopenharmony_ci        # Dollar style
40757db96d56Sopenharmony_ci        # Testing failure for mismatch bare $
40767db96d56Sopenharmony_ci        self.assert_error_message(
40777db96d56Sopenharmony_ci            ValueError,
40787db96d56Sopenharmony_ci            "invalid format: bare \'$\' not allowed",
40797db96d56Sopenharmony_ci            logging.Formatter, '$bar $$$', style='$'
40807db96d56Sopenharmony_ci        )
40817db96d56Sopenharmony_ci        self.assert_error_message(
40827db96d56Sopenharmony_ci            ValueError,
40837db96d56Sopenharmony_ci            "invalid format: bare \'$\' not allowed",
40847db96d56Sopenharmony_ci            logging.Formatter, 'bar $', style='$'
40857db96d56Sopenharmony_ci        )
40867db96d56Sopenharmony_ci        self.assert_error_message(
40877db96d56Sopenharmony_ci            ValueError,
40887db96d56Sopenharmony_ci            "invalid format: bare \'$\' not allowed",
40897db96d56Sopenharmony_ci            logging.Formatter, 'foo $.', style='$'
40907db96d56Sopenharmony_ci        )
40917db96d56Sopenharmony_ci        # Testing failure for mismatch style
40927db96d56Sopenharmony_ci        self.assert_error_message(
40937db96d56Sopenharmony_ci            ValueError,
40947db96d56Sopenharmony_ci            "invalid format: no fields",
40957db96d56Sopenharmony_ci            logging.Formatter, '{asctime}', style='$'
40967db96d56Sopenharmony_ci        )
40977db96d56Sopenharmony_ci        self.assertRaises(ValueError, logging.Formatter, '%(asctime)s', style='$')
40987db96d56Sopenharmony_ci
40997db96d56Sopenharmony_ci        # Testing failure for incorrect fields
41007db96d56Sopenharmony_ci        self.assert_error_message(
41017db96d56Sopenharmony_ci            ValueError,
41027db96d56Sopenharmony_ci            "invalid format: no fields",
41037db96d56Sopenharmony_ci            logging.Formatter, 'foo', style='$'
41047db96d56Sopenharmony_ci        )
41057db96d56Sopenharmony_ci        self.assertRaises(ValueError, logging.Formatter, '${asctime', style='$')
41067db96d56Sopenharmony_ci
41077db96d56Sopenharmony_ci    def test_defaults_parameter(self):
41087db96d56Sopenharmony_ci        fmts = ['%(custom)s %(message)s', '{custom} {message}', '$custom $message']
41097db96d56Sopenharmony_ci        styles = ['%', '{', '$']
41107db96d56Sopenharmony_ci        for fmt, style in zip(fmts, styles):
41117db96d56Sopenharmony_ci            f = logging.Formatter(fmt, style=style, defaults={'custom': 'Default'})
41127db96d56Sopenharmony_ci            r = self.get_record()
41137db96d56Sopenharmony_ci            self.assertEqual(f.format(r), 'Default Message with 2 placeholders')
41147db96d56Sopenharmony_ci            r = self.get_record("custom")
41157db96d56Sopenharmony_ci            self.assertEqual(f.format(r), '1234 Message with 2 placeholders')
41167db96d56Sopenharmony_ci
41177db96d56Sopenharmony_ci            # Without default
41187db96d56Sopenharmony_ci            f = logging.Formatter(fmt, style=style)
41197db96d56Sopenharmony_ci            r = self.get_record()
41207db96d56Sopenharmony_ci            self.assertRaises(ValueError, f.format, r)
41217db96d56Sopenharmony_ci
41227db96d56Sopenharmony_ci            # Non-existing default is ignored
41237db96d56Sopenharmony_ci            f = logging.Formatter(fmt, style=style, defaults={'Non-existing': 'Default'})
41247db96d56Sopenharmony_ci            r = self.get_record("custom")
41257db96d56Sopenharmony_ci            self.assertEqual(f.format(r), '1234 Message with 2 placeholders')
41267db96d56Sopenharmony_ci
41277db96d56Sopenharmony_ci    def test_invalid_style(self):
41287db96d56Sopenharmony_ci        self.assertRaises(ValueError, logging.Formatter, None, None, 'x')
41297db96d56Sopenharmony_ci
41307db96d56Sopenharmony_ci    def test_time(self):
41317db96d56Sopenharmony_ci        r = self.get_record()
41327db96d56Sopenharmony_ci        dt = datetime.datetime(1993, 4, 21, 8, 3, 0, 0, utc)
41337db96d56Sopenharmony_ci        # We use None to indicate we want the local timezone
41347db96d56Sopenharmony_ci        # We're essentially converting a UTC time to local time
41357db96d56Sopenharmony_ci        r.created = time.mktime(dt.astimezone(None).timetuple())
41367db96d56Sopenharmony_ci        r.msecs = 123
41377db96d56Sopenharmony_ci        f = logging.Formatter('%(asctime)s %(message)s')
41387db96d56Sopenharmony_ci        f.converter = time.gmtime
41397db96d56Sopenharmony_ci        self.assertEqual(f.formatTime(r), '1993-04-21 08:03:00,123')
41407db96d56Sopenharmony_ci        self.assertEqual(f.formatTime(r, '%Y:%d'), '1993:21')
41417db96d56Sopenharmony_ci        f.format(r)
41427db96d56Sopenharmony_ci        self.assertEqual(r.asctime, '1993-04-21 08:03:00,123')
41437db96d56Sopenharmony_ci
41447db96d56Sopenharmony_ci    def test_default_msec_format_none(self):
41457db96d56Sopenharmony_ci        class NoMsecFormatter(logging.Formatter):
41467db96d56Sopenharmony_ci            default_msec_format = None
41477db96d56Sopenharmony_ci            default_time_format = '%d/%m/%Y %H:%M:%S'
41487db96d56Sopenharmony_ci
41497db96d56Sopenharmony_ci        r = self.get_record()
41507db96d56Sopenharmony_ci        dt = datetime.datetime(1993, 4, 21, 8, 3, 0, 123, utc)
41517db96d56Sopenharmony_ci        r.created = time.mktime(dt.astimezone(None).timetuple())
41527db96d56Sopenharmony_ci        f = NoMsecFormatter()
41537db96d56Sopenharmony_ci        f.converter = time.gmtime
41547db96d56Sopenharmony_ci        self.assertEqual(f.formatTime(r), '21/04/1993 08:03:00')
41557db96d56Sopenharmony_ci
41567db96d56Sopenharmony_ci    def test_issue_89047(self):
41577db96d56Sopenharmony_ci        f = logging.Formatter(fmt='{asctime}.{msecs:03.0f} {message}', style='{', datefmt="%Y-%m-%d %H:%M:%S")
41587db96d56Sopenharmony_ci        for i in range(2500):
41597db96d56Sopenharmony_ci            time.sleep(0.0004)
41607db96d56Sopenharmony_ci            r = logging.makeLogRecord({'msg': 'Message %d' % (i + 1)})
41617db96d56Sopenharmony_ci            s = f.format(r)
41627db96d56Sopenharmony_ci            self.assertNotIn('.1000', s)
41637db96d56Sopenharmony_ci
41647db96d56Sopenharmony_ci
41657db96d56Sopenharmony_ciclass TestBufferingFormatter(logging.BufferingFormatter):
41667db96d56Sopenharmony_ci    def formatHeader(self, records):
41677db96d56Sopenharmony_ci        return '[(%d)' % len(records)
41687db96d56Sopenharmony_ci
41697db96d56Sopenharmony_ci    def formatFooter(self, records):
41707db96d56Sopenharmony_ci        return '(%d)]' % len(records)
41717db96d56Sopenharmony_ci
41727db96d56Sopenharmony_ciclass BufferingFormatterTest(unittest.TestCase):
41737db96d56Sopenharmony_ci    def setUp(self):
41747db96d56Sopenharmony_ci        self.records = [
41757db96d56Sopenharmony_ci            logging.makeLogRecord({'msg': 'one'}),
41767db96d56Sopenharmony_ci            logging.makeLogRecord({'msg': 'two'}),
41777db96d56Sopenharmony_ci        ]
41787db96d56Sopenharmony_ci
41797db96d56Sopenharmony_ci    def test_default(self):
41807db96d56Sopenharmony_ci        f = logging.BufferingFormatter()
41817db96d56Sopenharmony_ci        self.assertEqual('', f.format([]))
41827db96d56Sopenharmony_ci        self.assertEqual('onetwo', f.format(self.records))
41837db96d56Sopenharmony_ci
41847db96d56Sopenharmony_ci    def test_custom(self):
41857db96d56Sopenharmony_ci        f = TestBufferingFormatter()
41867db96d56Sopenharmony_ci        self.assertEqual('[(2)onetwo(2)]', f.format(self.records))
41877db96d56Sopenharmony_ci        lf = logging.Formatter('<%(message)s>')
41887db96d56Sopenharmony_ci        f = TestBufferingFormatter(lf)
41897db96d56Sopenharmony_ci        self.assertEqual('[(2)<one><two>(2)]', f.format(self.records))
41907db96d56Sopenharmony_ci
41917db96d56Sopenharmony_ciclass ExceptionTest(BaseTest):
41927db96d56Sopenharmony_ci    def test_formatting(self):
41937db96d56Sopenharmony_ci        r = self.root_logger
41947db96d56Sopenharmony_ci        h = RecordingHandler()
41957db96d56Sopenharmony_ci        r.addHandler(h)
41967db96d56Sopenharmony_ci        try:
41977db96d56Sopenharmony_ci            raise RuntimeError('deliberate mistake')
41987db96d56Sopenharmony_ci        except:
41997db96d56Sopenharmony_ci            logging.exception('failed', stack_info=True)
42007db96d56Sopenharmony_ci        r.removeHandler(h)
42017db96d56Sopenharmony_ci        h.close()
42027db96d56Sopenharmony_ci        r = h.records[0]
42037db96d56Sopenharmony_ci        self.assertTrue(r.exc_text.startswith('Traceback (most recent '
42047db96d56Sopenharmony_ci                                              'call last):\n'))
42057db96d56Sopenharmony_ci        self.assertTrue(r.exc_text.endswith('\nRuntimeError: '
42067db96d56Sopenharmony_ci                                            'deliberate mistake'))
42077db96d56Sopenharmony_ci        self.assertTrue(r.stack_info.startswith('Stack (most recent '
42087db96d56Sopenharmony_ci                                              'call last):\n'))
42097db96d56Sopenharmony_ci        self.assertTrue(r.stack_info.endswith('logging.exception(\'failed\', '
42107db96d56Sopenharmony_ci                                            'stack_info=True)'))
42117db96d56Sopenharmony_ci
42127db96d56Sopenharmony_ci
42137db96d56Sopenharmony_ciclass LastResortTest(BaseTest):
42147db96d56Sopenharmony_ci    def test_last_resort(self):
42157db96d56Sopenharmony_ci        # Test the last resort handler
42167db96d56Sopenharmony_ci        root = self.root_logger
42177db96d56Sopenharmony_ci        root.removeHandler(self.root_hdlr)
42187db96d56Sopenharmony_ci        old_lastresort = logging.lastResort
42197db96d56Sopenharmony_ci        old_raise_exceptions = logging.raiseExceptions
42207db96d56Sopenharmony_ci
42217db96d56Sopenharmony_ci        try:
42227db96d56Sopenharmony_ci            with support.captured_stderr() as stderr:
42237db96d56Sopenharmony_ci                root.debug('This should not appear')
42247db96d56Sopenharmony_ci                self.assertEqual(stderr.getvalue(), '')
42257db96d56Sopenharmony_ci                root.warning('Final chance!')
42267db96d56Sopenharmony_ci                self.assertEqual(stderr.getvalue(), 'Final chance!\n')
42277db96d56Sopenharmony_ci
42287db96d56Sopenharmony_ci            # No handlers and no last resort, so 'No handlers' message
42297db96d56Sopenharmony_ci            logging.lastResort = None
42307db96d56Sopenharmony_ci            with support.captured_stderr() as stderr:
42317db96d56Sopenharmony_ci                root.warning('Final chance!')
42327db96d56Sopenharmony_ci                msg = 'No handlers could be found for logger "root"\n'
42337db96d56Sopenharmony_ci                self.assertEqual(stderr.getvalue(), msg)
42347db96d56Sopenharmony_ci
42357db96d56Sopenharmony_ci            # 'No handlers' message only printed once
42367db96d56Sopenharmony_ci            with support.captured_stderr() as stderr:
42377db96d56Sopenharmony_ci                root.warning('Final chance!')
42387db96d56Sopenharmony_ci                self.assertEqual(stderr.getvalue(), '')
42397db96d56Sopenharmony_ci
42407db96d56Sopenharmony_ci            # If raiseExceptions is False, no message is printed
42417db96d56Sopenharmony_ci            root.manager.emittedNoHandlerWarning = False
42427db96d56Sopenharmony_ci            logging.raiseExceptions = False
42437db96d56Sopenharmony_ci            with support.captured_stderr() as stderr:
42447db96d56Sopenharmony_ci                root.warning('Final chance!')
42457db96d56Sopenharmony_ci                self.assertEqual(stderr.getvalue(), '')
42467db96d56Sopenharmony_ci        finally:
42477db96d56Sopenharmony_ci            root.addHandler(self.root_hdlr)
42487db96d56Sopenharmony_ci            logging.lastResort = old_lastresort
42497db96d56Sopenharmony_ci            logging.raiseExceptions = old_raise_exceptions
42507db96d56Sopenharmony_ci
42517db96d56Sopenharmony_ci
42527db96d56Sopenharmony_ciclass FakeHandler:
42537db96d56Sopenharmony_ci
42547db96d56Sopenharmony_ci    def __init__(self, identifier, called):
42557db96d56Sopenharmony_ci        for method in ('acquire', 'flush', 'close', 'release'):
42567db96d56Sopenharmony_ci            setattr(self, method, self.record_call(identifier, method, called))
42577db96d56Sopenharmony_ci
42587db96d56Sopenharmony_ci    def record_call(self, identifier, method_name, called):
42597db96d56Sopenharmony_ci        def inner():
42607db96d56Sopenharmony_ci            called.append('{} - {}'.format(identifier, method_name))
42617db96d56Sopenharmony_ci        return inner
42627db96d56Sopenharmony_ci
42637db96d56Sopenharmony_ci
42647db96d56Sopenharmony_ciclass RecordingHandler(logging.NullHandler):
42657db96d56Sopenharmony_ci
42667db96d56Sopenharmony_ci    def __init__(self, *args, **kwargs):
42677db96d56Sopenharmony_ci        super(RecordingHandler, self).__init__(*args, **kwargs)
42687db96d56Sopenharmony_ci        self.records = []
42697db96d56Sopenharmony_ci
42707db96d56Sopenharmony_ci    def handle(self, record):
42717db96d56Sopenharmony_ci        """Keep track of all the emitted records."""
42727db96d56Sopenharmony_ci        self.records.append(record)
42737db96d56Sopenharmony_ci
42747db96d56Sopenharmony_ci
42757db96d56Sopenharmony_ciclass ShutdownTest(BaseTest):
42767db96d56Sopenharmony_ci
42777db96d56Sopenharmony_ci    """Test suite for the shutdown method."""
42787db96d56Sopenharmony_ci
42797db96d56Sopenharmony_ci    def setUp(self):
42807db96d56Sopenharmony_ci        super(ShutdownTest, self).setUp()
42817db96d56Sopenharmony_ci        self.called = []
42827db96d56Sopenharmony_ci
42837db96d56Sopenharmony_ci        raise_exceptions = logging.raiseExceptions
42847db96d56Sopenharmony_ci        self.addCleanup(setattr, logging, 'raiseExceptions', raise_exceptions)
42857db96d56Sopenharmony_ci
42867db96d56Sopenharmony_ci    def raise_error(self, error):
42877db96d56Sopenharmony_ci        def inner():
42887db96d56Sopenharmony_ci            raise error()
42897db96d56Sopenharmony_ci        return inner
42907db96d56Sopenharmony_ci
42917db96d56Sopenharmony_ci    def test_no_failure(self):
42927db96d56Sopenharmony_ci        # create some fake handlers
42937db96d56Sopenharmony_ci        handler0 = FakeHandler(0, self.called)
42947db96d56Sopenharmony_ci        handler1 = FakeHandler(1, self.called)
42957db96d56Sopenharmony_ci        handler2 = FakeHandler(2, self.called)
42967db96d56Sopenharmony_ci
42977db96d56Sopenharmony_ci        # create live weakref to those handlers
42987db96d56Sopenharmony_ci        handlers = map(logging.weakref.ref, [handler0, handler1, handler2])
42997db96d56Sopenharmony_ci
43007db96d56Sopenharmony_ci        logging.shutdown(handlerList=list(handlers))
43017db96d56Sopenharmony_ci
43027db96d56Sopenharmony_ci        expected = ['2 - acquire', '2 - flush', '2 - close', '2 - release',
43037db96d56Sopenharmony_ci                    '1 - acquire', '1 - flush', '1 - close', '1 - release',
43047db96d56Sopenharmony_ci                    '0 - acquire', '0 - flush', '0 - close', '0 - release']
43057db96d56Sopenharmony_ci        self.assertEqual(expected, self.called)
43067db96d56Sopenharmony_ci
43077db96d56Sopenharmony_ci    def _test_with_failure_in_method(self, method, error):
43087db96d56Sopenharmony_ci        handler = FakeHandler(0, self.called)
43097db96d56Sopenharmony_ci        setattr(handler, method, self.raise_error(error))
43107db96d56Sopenharmony_ci        handlers = [logging.weakref.ref(handler)]
43117db96d56Sopenharmony_ci
43127db96d56Sopenharmony_ci        logging.shutdown(handlerList=list(handlers))
43137db96d56Sopenharmony_ci
43147db96d56Sopenharmony_ci        self.assertEqual('0 - release', self.called[-1])
43157db96d56Sopenharmony_ci
43167db96d56Sopenharmony_ci    def test_with_ioerror_in_acquire(self):
43177db96d56Sopenharmony_ci        self._test_with_failure_in_method('acquire', OSError)
43187db96d56Sopenharmony_ci
43197db96d56Sopenharmony_ci    def test_with_ioerror_in_flush(self):
43207db96d56Sopenharmony_ci        self._test_with_failure_in_method('flush', OSError)
43217db96d56Sopenharmony_ci
43227db96d56Sopenharmony_ci    def test_with_ioerror_in_close(self):
43237db96d56Sopenharmony_ci        self._test_with_failure_in_method('close', OSError)
43247db96d56Sopenharmony_ci
43257db96d56Sopenharmony_ci    def test_with_valueerror_in_acquire(self):
43267db96d56Sopenharmony_ci        self._test_with_failure_in_method('acquire', ValueError)
43277db96d56Sopenharmony_ci
43287db96d56Sopenharmony_ci    def test_with_valueerror_in_flush(self):
43297db96d56Sopenharmony_ci        self._test_with_failure_in_method('flush', ValueError)
43307db96d56Sopenharmony_ci
43317db96d56Sopenharmony_ci    def test_with_valueerror_in_close(self):
43327db96d56Sopenharmony_ci        self._test_with_failure_in_method('close', ValueError)
43337db96d56Sopenharmony_ci
43347db96d56Sopenharmony_ci    def test_with_other_error_in_acquire_without_raise(self):
43357db96d56Sopenharmony_ci        logging.raiseExceptions = False
43367db96d56Sopenharmony_ci        self._test_with_failure_in_method('acquire', IndexError)
43377db96d56Sopenharmony_ci
43387db96d56Sopenharmony_ci    def test_with_other_error_in_flush_without_raise(self):
43397db96d56Sopenharmony_ci        logging.raiseExceptions = False
43407db96d56Sopenharmony_ci        self._test_with_failure_in_method('flush', IndexError)
43417db96d56Sopenharmony_ci
43427db96d56Sopenharmony_ci    def test_with_other_error_in_close_without_raise(self):
43437db96d56Sopenharmony_ci        logging.raiseExceptions = False
43447db96d56Sopenharmony_ci        self._test_with_failure_in_method('close', IndexError)
43457db96d56Sopenharmony_ci
43467db96d56Sopenharmony_ci    def test_with_other_error_in_acquire_with_raise(self):
43477db96d56Sopenharmony_ci        logging.raiseExceptions = True
43487db96d56Sopenharmony_ci        self.assertRaises(IndexError, self._test_with_failure_in_method,
43497db96d56Sopenharmony_ci                          'acquire', IndexError)
43507db96d56Sopenharmony_ci
43517db96d56Sopenharmony_ci    def test_with_other_error_in_flush_with_raise(self):
43527db96d56Sopenharmony_ci        logging.raiseExceptions = True
43537db96d56Sopenharmony_ci        self.assertRaises(IndexError, self._test_with_failure_in_method,
43547db96d56Sopenharmony_ci                          'flush', IndexError)
43557db96d56Sopenharmony_ci
43567db96d56Sopenharmony_ci    def test_with_other_error_in_close_with_raise(self):
43577db96d56Sopenharmony_ci        logging.raiseExceptions = True
43587db96d56Sopenharmony_ci        self.assertRaises(IndexError, self._test_with_failure_in_method,
43597db96d56Sopenharmony_ci                          'close', IndexError)
43607db96d56Sopenharmony_ci
43617db96d56Sopenharmony_ci
43627db96d56Sopenharmony_ciclass ModuleLevelMiscTest(BaseTest):
43637db96d56Sopenharmony_ci
43647db96d56Sopenharmony_ci    """Test suite for some module level methods."""
43657db96d56Sopenharmony_ci
43667db96d56Sopenharmony_ci    def test_disable(self):
43677db96d56Sopenharmony_ci        old_disable = logging.root.manager.disable
43687db96d56Sopenharmony_ci        # confirm our assumptions are correct
43697db96d56Sopenharmony_ci        self.assertEqual(old_disable, 0)
43707db96d56Sopenharmony_ci        self.addCleanup(logging.disable, old_disable)
43717db96d56Sopenharmony_ci
43727db96d56Sopenharmony_ci        logging.disable(83)
43737db96d56Sopenharmony_ci        self.assertEqual(logging.root.manager.disable, 83)
43747db96d56Sopenharmony_ci
43757db96d56Sopenharmony_ci        self.assertRaises(ValueError, logging.disable, "doesnotexists")
43767db96d56Sopenharmony_ci
43777db96d56Sopenharmony_ci        class _NotAnIntOrString:
43787db96d56Sopenharmony_ci            pass
43797db96d56Sopenharmony_ci
43807db96d56Sopenharmony_ci        self.assertRaises(TypeError, logging.disable, _NotAnIntOrString())
43817db96d56Sopenharmony_ci
43827db96d56Sopenharmony_ci        logging.disable("WARN")
43837db96d56Sopenharmony_ci
43847db96d56Sopenharmony_ci        # test the default value introduced in 3.7
43857db96d56Sopenharmony_ci        # (Issue #28524)
43867db96d56Sopenharmony_ci        logging.disable()
43877db96d56Sopenharmony_ci        self.assertEqual(logging.root.manager.disable, logging.CRITICAL)
43887db96d56Sopenharmony_ci
43897db96d56Sopenharmony_ci    def _test_log(self, method, level=None):
43907db96d56Sopenharmony_ci        called = []
43917db96d56Sopenharmony_ci        support.patch(self, logging, 'basicConfig',
43927db96d56Sopenharmony_ci                      lambda *a, **kw: called.append((a, kw)))
43937db96d56Sopenharmony_ci
43947db96d56Sopenharmony_ci        recording = RecordingHandler()
43957db96d56Sopenharmony_ci        logging.root.addHandler(recording)
43967db96d56Sopenharmony_ci
43977db96d56Sopenharmony_ci        log_method = getattr(logging, method)
43987db96d56Sopenharmony_ci        if level is not None:
43997db96d56Sopenharmony_ci            log_method(level, "test me: %r", recording)
44007db96d56Sopenharmony_ci        else:
44017db96d56Sopenharmony_ci            log_method("test me: %r", recording)
44027db96d56Sopenharmony_ci
44037db96d56Sopenharmony_ci        self.assertEqual(len(recording.records), 1)
44047db96d56Sopenharmony_ci        record = recording.records[0]
44057db96d56Sopenharmony_ci        self.assertEqual(record.getMessage(), "test me: %r" % recording)
44067db96d56Sopenharmony_ci
44077db96d56Sopenharmony_ci        expected_level = level if level is not None else getattr(logging, method.upper())
44087db96d56Sopenharmony_ci        self.assertEqual(record.levelno, expected_level)
44097db96d56Sopenharmony_ci
44107db96d56Sopenharmony_ci        # basicConfig was not called!
44117db96d56Sopenharmony_ci        self.assertEqual(called, [])
44127db96d56Sopenharmony_ci
44137db96d56Sopenharmony_ci    def test_log(self):
44147db96d56Sopenharmony_ci        self._test_log('log', logging.ERROR)
44157db96d56Sopenharmony_ci
44167db96d56Sopenharmony_ci    def test_debug(self):
44177db96d56Sopenharmony_ci        self._test_log('debug')
44187db96d56Sopenharmony_ci
44197db96d56Sopenharmony_ci    def test_info(self):
44207db96d56Sopenharmony_ci        self._test_log('info')
44217db96d56Sopenharmony_ci
44227db96d56Sopenharmony_ci    def test_warning(self):
44237db96d56Sopenharmony_ci        self._test_log('warning')
44247db96d56Sopenharmony_ci
44257db96d56Sopenharmony_ci    def test_error(self):
44267db96d56Sopenharmony_ci        self._test_log('error')
44277db96d56Sopenharmony_ci
44287db96d56Sopenharmony_ci    def test_critical(self):
44297db96d56Sopenharmony_ci        self._test_log('critical')
44307db96d56Sopenharmony_ci
44317db96d56Sopenharmony_ci    def test_set_logger_class(self):
44327db96d56Sopenharmony_ci        self.assertRaises(TypeError, logging.setLoggerClass, object)
44337db96d56Sopenharmony_ci
44347db96d56Sopenharmony_ci        class MyLogger(logging.Logger):
44357db96d56Sopenharmony_ci            pass
44367db96d56Sopenharmony_ci
44377db96d56Sopenharmony_ci        logging.setLoggerClass(MyLogger)
44387db96d56Sopenharmony_ci        self.assertEqual(logging.getLoggerClass(), MyLogger)
44397db96d56Sopenharmony_ci
44407db96d56Sopenharmony_ci        logging.setLoggerClass(logging.Logger)
44417db96d56Sopenharmony_ci        self.assertEqual(logging.getLoggerClass(), logging.Logger)
44427db96d56Sopenharmony_ci
44437db96d56Sopenharmony_ci    def test_subclass_logger_cache(self):
44447db96d56Sopenharmony_ci        # bpo-37258
44457db96d56Sopenharmony_ci        message = []
44467db96d56Sopenharmony_ci
44477db96d56Sopenharmony_ci        class MyLogger(logging.getLoggerClass()):
44487db96d56Sopenharmony_ci            def __init__(self, name='MyLogger', level=logging.NOTSET):
44497db96d56Sopenharmony_ci                super().__init__(name, level)
44507db96d56Sopenharmony_ci                message.append('initialized')
44517db96d56Sopenharmony_ci
44527db96d56Sopenharmony_ci        logging.setLoggerClass(MyLogger)
44537db96d56Sopenharmony_ci        logger = logging.getLogger('just_some_logger')
44547db96d56Sopenharmony_ci        self.assertEqual(message, ['initialized'])
44557db96d56Sopenharmony_ci        stream = io.StringIO()
44567db96d56Sopenharmony_ci        h = logging.StreamHandler(stream)
44577db96d56Sopenharmony_ci        logger.addHandler(h)
44587db96d56Sopenharmony_ci        try:
44597db96d56Sopenharmony_ci            logger.setLevel(logging.DEBUG)
44607db96d56Sopenharmony_ci            logger.debug("hello")
44617db96d56Sopenharmony_ci            self.assertEqual(stream.getvalue().strip(), "hello")
44627db96d56Sopenharmony_ci
44637db96d56Sopenharmony_ci            stream.truncate(0)
44647db96d56Sopenharmony_ci            stream.seek(0)
44657db96d56Sopenharmony_ci
44667db96d56Sopenharmony_ci            logger.setLevel(logging.INFO)
44677db96d56Sopenharmony_ci            logger.debug("hello")
44687db96d56Sopenharmony_ci            self.assertEqual(stream.getvalue(), "")
44697db96d56Sopenharmony_ci        finally:
44707db96d56Sopenharmony_ci            logger.removeHandler(h)
44717db96d56Sopenharmony_ci            h.close()
44727db96d56Sopenharmony_ci            logging.setLoggerClass(logging.Logger)
44737db96d56Sopenharmony_ci
44747db96d56Sopenharmony_ci    def test_logging_at_shutdown(self):
44757db96d56Sopenharmony_ci        # bpo-20037: Doing text I/O late at interpreter shutdown must not crash
44767db96d56Sopenharmony_ci        code = textwrap.dedent("""
44777db96d56Sopenharmony_ci            import logging
44787db96d56Sopenharmony_ci
44797db96d56Sopenharmony_ci            class A:
44807db96d56Sopenharmony_ci                def __del__(self):
44817db96d56Sopenharmony_ci                    try:
44827db96d56Sopenharmony_ci                        raise ValueError("some error")
44837db96d56Sopenharmony_ci                    except Exception:
44847db96d56Sopenharmony_ci                        logging.exception("exception in __del__")
44857db96d56Sopenharmony_ci
44867db96d56Sopenharmony_ci            a = A()
44877db96d56Sopenharmony_ci        """)
44887db96d56Sopenharmony_ci        rc, out, err = assert_python_ok("-c", code)
44897db96d56Sopenharmony_ci        err = err.decode()
44907db96d56Sopenharmony_ci        self.assertIn("exception in __del__", err)
44917db96d56Sopenharmony_ci        self.assertIn("ValueError: some error", err)
44927db96d56Sopenharmony_ci
44937db96d56Sopenharmony_ci    def test_logging_at_shutdown_open(self):
44947db96d56Sopenharmony_ci        # bpo-26789: FileHandler keeps a reference to the builtin open()
44957db96d56Sopenharmony_ci        # function to be able to open or reopen the file during Python
44967db96d56Sopenharmony_ci        # finalization.
44977db96d56Sopenharmony_ci        filename = os_helper.TESTFN
44987db96d56Sopenharmony_ci        self.addCleanup(os_helper.unlink, filename)
44997db96d56Sopenharmony_ci
45007db96d56Sopenharmony_ci        code = textwrap.dedent(f"""
45017db96d56Sopenharmony_ci            import builtins
45027db96d56Sopenharmony_ci            import logging
45037db96d56Sopenharmony_ci
45047db96d56Sopenharmony_ci            class A:
45057db96d56Sopenharmony_ci                def __del__(self):
45067db96d56Sopenharmony_ci                    logging.error("log in __del__")
45077db96d56Sopenharmony_ci
45087db96d56Sopenharmony_ci            # basicConfig() opens the file, but logging.shutdown() closes
45097db96d56Sopenharmony_ci            # it at Python exit. When A.__del__() is called,
45107db96d56Sopenharmony_ci            # FileHandler._open() must be called again to re-open the file.
45117db96d56Sopenharmony_ci            logging.basicConfig(filename={filename!r}, encoding="utf-8")
45127db96d56Sopenharmony_ci
45137db96d56Sopenharmony_ci            a = A()
45147db96d56Sopenharmony_ci
45157db96d56Sopenharmony_ci            # Simulate the Python finalization which removes the builtin
45167db96d56Sopenharmony_ci            # open() function.
45177db96d56Sopenharmony_ci            del builtins.open
45187db96d56Sopenharmony_ci        """)
45197db96d56Sopenharmony_ci        assert_python_ok("-c", code)
45207db96d56Sopenharmony_ci
45217db96d56Sopenharmony_ci        with open(filename, encoding="utf-8") as fp:
45227db96d56Sopenharmony_ci            self.assertEqual(fp.read().rstrip(), "ERROR:root:log in __del__")
45237db96d56Sopenharmony_ci
45247db96d56Sopenharmony_ci    def test_recursion_error(self):
45257db96d56Sopenharmony_ci        # Issue 36272
45267db96d56Sopenharmony_ci        code = textwrap.dedent("""
45277db96d56Sopenharmony_ci            import logging
45287db96d56Sopenharmony_ci
45297db96d56Sopenharmony_ci            def rec():
45307db96d56Sopenharmony_ci                logging.error("foo")
45317db96d56Sopenharmony_ci                rec()
45327db96d56Sopenharmony_ci
45337db96d56Sopenharmony_ci            rec()
45347db96d56Sopenharmony_ci        """)
45357db96d56Sopenharmony_ci        rc, out, err = assert_python_failure("-c", code)
45367db96d56Sopenharmony_ci        err = err.decode()
45377db96d56Sopenharmony_ci        self.assertNotIn("Cannot recover from stack overflow.", err)
45387db96d56Sopenharmony_ci        self.assertEqual(rc, 1)
45397db96d56Sopenharmony_ci
45407db96d56Sopenharmony_ci    def test_get_level_names_mapping(self):
45417db96d56Sopenharmony_ci        mapping = logging.getLevelNamesMapping()
45427db96d56Sopenharmony_ci        self.assertEqual(logging._nameToLevel, mapping)  # value is equivalent
45437db96d56Sopenharmony_ci        self.assertIsNot(logging._nameToLevel, mapping)  # but not the internal data
45447db96d56Sopenharmony_ci        new_mapping = logging.getLevelNamesMapping()     # another call -> another copy
45457db96d56Sopenharmony_ci        self.assertIsNot(mapping, new_mapping)           # verify not the same object as before
45467db96d56Sopenharmony_ci        self.assertEqual(mapping, new_mapping)           # but equivalent in value
45477db96d56Sopenharmony_ci
45487db96d56Sopenharmony_ci
45497db96d56Sopenharmony_ciclass LogRecordTest(BaseTest):
45507db96d56Sopenharmony_ci    def test_str_rep(self):
45517db96d56Sopenharmony_ci        r = logging.makeLogRecord({})
45527db96d56Sopenharmony_ci        s = str(r)
45537db96d56Sopenharmony_ci        self.assertTrue(s.startswith('<LogRecord: '))
45547db96d56Sopenharmony_ci        self.assertTrue(s.endswith('>'))
45557db96d56Sopenharmony_ci
45567db96d56Sopenharmony_ci    def test_dict_arg(self):
45577db96d56Sopenharmony_ci        h = RecordingHandler()
45587db96d56Sopenharmony_ci        r = logging.getLogger()
45597db96d56Sopenharmony_ci        r.addHandler(h)
45607db96d56Sopenharmony_ci        d = {'less' : 'more' }
45617db96d56Sopenharmony_ci        logging.warning('less is %(less)s', d)
45627db96d56Sopenharmony_ci        self.assertIs(h.records[0].args, d)
45637db96d56Sopenharmony_ci        self.assertEqual(h.records[0].message, 'less is more')
45647db96d56Sopenharmony_ci        r.removeHandler(h)
45657db96d56Sopenharmony_ci        h.close()
45667db96d56Sopenharmony_ci
45677db96d56Sopenharmony_ci    @staticmethod # pickled as target of child process in the following test
45687db96d56Sopenharmony_ci    def _extract_logrecord_process_name(key, logMultiprocessing, conn=None):
45697db96d56Sopenharmony_ci        prev_logMultiprocessing = logging.logMultiprocessing
45707db96d56Sopenharmony_ci        logging.logMultiprocessing = logMultiprocessing
45717db96d56Sopenharmony_ci        try:
45727db96d56Sopenharmony_ci            import multiprocessing as mp
45737db96d56Sopenharmony_ci            name = mp.current_process().name
45747db96d56Sopenharmony_ci
45757db96d56Sopenharmony_ci            r1 = logging.makeLogRecord({'msg': f'msg1_{key}'})
45767db96d56Sopenharmony_ci
45777db96d56Sopenharmony_ci            # https://bugs.python.org/issue45128
45787db96d56Sopenharmony_ci            with support.swap_item(sys.modules, 'multiprocessing', None):
45797db96d56Sopenharmony_ci                r2 = logging.makeLogRecord({'msg': f'msg2_{key}'})
45807db96d56Sopenharmony_ci
45817db96d56Sopenharmony_ci            results = {'processName'  : name,
45827db96d56Sopenharmony_ci                       'r1.processName': r1.processName,
45837db96d56Sopenharmony_ci                       'r2.processName': r2.processName,
45847db96d56Sopenharmony_ci                      }
45857db96d56Sopenharmony_ci        finally:
45867db96d56Sopenharmony_ci            logging.logMultiprocessing = prev_logMultiprocessing
45877db96d56Sopenharmony_ci        if conn:
45887db96d56Sopenharmony_ci            conn.send(results)
45897db96d56Sopenharmony_ci        else:
45907db96d56Sopenharmony_ci            return results
45917db96d56Sopenharmony_ci
45927db96d56Sopenharmony_ci    def test_multiprocessing(self):
45937db96d56Sopenharmony_ci        support.skip_if_broken_multiprocessing_synchronize()
45947db96d56Sopenharmony_ci        multiprocessing_imported = 'multiprocessing' in sys.modules
45957db96d56Sopenharmony_ci        try:
45967db96d56Sopenharmony_ci            # logMultiprocessing is True by default
45977db96d56Sopenharmony_ci            self.assertEqual(logging.logMultiprocessing, True)
45987db96d56Sopenharmony_ci
45997db96d56Sopenharmony_ci            LOG_MULTI_PROCESSING = True
46007db96d56Sopenharmony_ci            # When logMultiprocessing == True:
46017db96d56Sopenharmony_ci            # In the main process processName = 'MainProcess'
46027db96d56Sopenharmony_ci            r = logging.makeLogRecord({})
46037db96d56Sopenharmony_ci            self.assertEqual(r.processName, 'MainProcess')
46047db96d56Sopenharmony_ci
46057db96d56Sopenharmony_ci            results = self._extract_logrecord_process_name(1, LOG_MULTI_PROCESSING)
46067db96d56Sopenharmony_ci            self.assertEqual('MainProcess', results['processName'])
46077db96d56Sopenharmony_ci            self.assertEqual('MainProcess', results['r1.processName'])
46087db96d56Sopenharmony_ci            self.assertEqual('MainProcess', results['r2.processName'])
46097db96d56Sopenharmony_ci
46107db96d56Sopenharmony_ci            # In other processes, processName is correct when multiprocessing in imported,
46117db96d56Sopenharmony_ci            # but it is (incorrectly) defaulted to 'MainProcess' otherwise (bpo-38762).
46127db96d56Sopenharmony_ci            import multiprocessing
46137db96d56Sopenharmony_ci            parent_conn, child_conn = multiprocessing.Pipe()
46147db96d56Sopenharmony_ci            p = multiprocessing.Process(
46157db96d56Sopenharmony_ci                target=self._extract_logrecord_process_name,
46167db96d56Sopenharmony_ci                args=(2, LOG_MULTI_PROCESSING, child_conn,)
46177db96d56Sopenharmony_ci            )
46187db96d56Sopenharmony_ci            p.start()
46197db96d56Sopenharmony_ci            results = parent_conn.recv()
46207db96d56Sopenharmony_ci            self.assertNotEqual('MainProcess', results['processName'])
46217db96d56Sopenharmony_ci            self.assertEqual(results['processName'], results['r1.processName'])
46227db96d56Sopenharmony_ci            self.assertEqual('MainProcess', results['r2.processName'])
46237db96d56Sopenharmony_ci            p.join()
46247db96d56Sopenharmony_ci
46257db96d56Sopenharmony_ci        finally:
46267db96d56Sopenharmony_ci            if multiprocessing_imported:
46277db96d56Sopenharmony_ci                import multiprocessing
46287db96d56Sopenharmony_ci
46297db96d56Sopenharmony_ci    def test_optional(self):
46307db96d56Sopenharmony_ci        r = logging.makeLogRecord({})
46317db96d56Sopenharmony_ci        NOT_NONE = self.assertIsNotNone
46327db96d56Sopenharmony_ci        NOT_NONE(r.thread)
46337db96d56Sopenharmony_ci        NOT_NONE(r.threadName)
46347db96d56Sopenharmony_ci        NOT_NONE(r.process)
46357db96d56Sopenharmony_ci        NOT_NONE(r.processName)
46367db96d56Sopenharmony_ci        log_threads = logging.logThreads
46377db96d56Sopenharmony_ci        log_processes = logging.logProcesses
46387db96d56Sopenharmony_ci        log_multiprocessing = logging.logMultiprocessing
46397db96d56Sopenharmony_ci        try:
46407db96d56Sopenharmony_ci            logging.logThreads = False
46417db96d56Sopenharmony_ci            logging.logProcesses = False
46427db96d56Sopenharmony_ci            logging.logMultiprocessing = False
46437db96d56Sopenharmony_ci            r = logging.makeLogRecord({})
46447db96d56Sopenharmony_ci            NONE = self.assertIsNone
46457db96d56Sopenharmony_ci            NONE(r.thread)
46467db96d56Sopenharmony_ci            NONE(r.threadName)
46477db96d56Sopenharmony_ci            NONE(r.process)
46487db96d56Sopenharmony_ci            NONE(r.processName)
46497db96d56Sopenharmony_ci        finally:
46507db96d56Sopenharmony_ci            logging.logThreads = log_threads
46517db96d56Sopenharmony_ci            logging.logProcesses = log_processes
46527db96d56Sopenharmony_ci            logging.logMultiprocessing = log_multiprocessing
46537db96d56Sopenharmony_ci
46547db96d56Sopenharmony_ciclass BasicConfigTest(unittest.TestCase):
46557db96d56Sopenharmony_ci
46567db96d56Sopenharmony_ci    """Test suite for logging.basicConfig."""
46577db96d56Sopenharmony_ci
46587db96d56Sopenharmony_ci    def setUp(self):
46597db96d56Sopenharmony_ci        super(BasicConfigTest, self).setUp()
46607db96d56Sopenharmony_ci        self.handlers = logging.root.handlers
46617db96d56Sopenharmony_ci        self.saved_handlers = logging._handlers.copy()
46627db96d56Sopenharmony_ci        self.saved_handler_list = logging._handlerList[:]
46637db96d56Sopenharmony_ci        self.original_logging_level = logging.root.level
46647db96d56Sopenharmony_ci        self.addCleanup(self.cleanup)
46657db96d56Sopenharmony_ci        logging.root.handlers = []
46667db96d56Sopenharmony_ci
46677db96d56Sopenharmony_ci    def tearDown(self):
46687db96d56Sopenharmony_ci        for h in logging.root.handlers[:]:
46697db96d56Sopenharmony_ci            logging.root.removeHandler(h)
46707db96d56Sopenharmony_ci            h.close()
46717db96d56Sopenharmony_ci        super(BasicConfigTest, self).tearDown()
46727db96d56Sopenharmony_ci
46737db96d56Sopenharmony_ci    def cleanup(self):
46747db96d56Sopenharmony_ci        setattr(logging.root, 'handlers', self.handlers)
46757db96d56Sopenharmony_ci        logging._handlers.clear()
46767db96d56Sopenharmony_ci        logging._handlers.update(self.saved_handlers)
46777db96d56Sopenharmony_ci        logging._handlerList[:] = self.saved_handler_list
46787db96d56Sopenharmony_ci        logging.root.setLevel(self.original_logging_level)
46797db96d56Sopenharmony_ci
46807db96d56Sopenharmony_ci    def test_no_kwargs(self):
46817db96d56Sopenharmony_ci        logging.basicConfig()
46827db96d56Sopenharmony_ci
46837db96d56Sopenharmony_ci        # handler defaults to a StreamHandler to sys.stderr
46847db96d56Sopenharmony_ci        self.assertEqual(len(logging.root.handlers), 1)
46857db96d56Sopenharmony_ci        handler = logging.root.handlers[0]
46867db96d56Sopenharmony_ci        self.assertIsInstance(handler, logging.StreamHandler)
46877db96d56Sopenharmony_ci        self.assertEqual(handler.stream, sys.stderr)
46887db96d56Sopenharmony_ci
46897db96d56Sopenharmony_ci        formatter = handler.formatter
46907db96d56Sopenharmony_ci        # format defaults to logging.BASIC_FORMAT
46917db96d56Sopenharmony_ci        self.assertEqual(formatter._style._fmt, logging.BASIC_FORMAT)
46927db96d56Sopenharmony_ci        # datefmt defaults to None
46937db96d56Sopenharmony_ci        self.assertIsNone(formatter.datefmt)
46947db96d56Sopenharmony_ci        # style defaults to %
46957db96d56Sopenharmony_ci        self.assertIsInstance(formatter._style, logging.PercentStyle)
46967db96d56Sopenharmony_ci
46977db96d56Sopenharmony_ci        # level is not explicitly set
46987db96d56Sopenharmony_ci        self.assertEqual(logging.root.level, self.original_logging_level)
46997db96d56Sopenharmony_ci
47007db96d56Sopenharmony_ci    def test_strformatstyle(self):
47017db96d56Sopenharmony_ci        with support.captured_stdout() as output:
47027db96d56Sopenharmony_ci            logging.basicConfig(stream=sys.stdout, style="{")
47037db96d56Sopenharmony_ci            logging.error("Log an error")
47047db96d56Sopenharmony_ci            sys.stdout.seek(0)
47057db96d56Sopenharmony_ci            self.assertEqual(output.getvalue().strip(),
47067db96d56Sopenharmony_ci                "ERROR:root:Log an error")
47077db96d56Sopenharmony_ci
47087db96d56Sopenharmony_ci    def test_stringtemplatestyle(self):
47097db96d56Sopenharmony_ci        with support.captured_stdout() as output:
47107db96d56Sopenharmony_ci            logging.basicConfig(stream=sys.stdout, style="$")
47117db96d56Sopenharmony_ci            logging.error("Log an error")
47127db96d56Sopenharmony_ci            sys.stdout.seek(0)
47137db96d56Sopenharmony_ci            self.assertEqual(output.getvalue().strip(),
47147db96d56Sopenharmony_ci                "ERROR:root:Log an error")
47157db96d56Sopenharmony_ci
47167db96d56Sopenharmony_ci    def test_filename(self):
47177db96d56Sopenharmony_ci
47187db96d56Sopenharmony_ci        def cleanup(h1, h2, fn):
47197db96d56Sopenharmony_ci            h1.close()
47207db96d56Sopenharmony_ci            h2.close()
47217db96d56Sopenharmony_ci            os.remove(fn)
47227db96d56Sopenharmony_ci
47237db96d56Sopenharmony_ci        logging.basicConfig(filename='test.log', encoding='utf-8')
47247db96d56Sopenharmony_ci
47257db96d56Sopenharmony_ci        self.assertEqual(len(logging.root.handlers), 1)
47267db96d56Sopenharmony_ci        handler = logging.root.handlers[0]
47277db96d56Sopenharmony_ci        self.assertIsInstance(handler, logging.FileHandler)
47287db96d56Sopenharmony_ci
47297db96d56Sopenharmony_ci        expected = logging.FileHandler('test.log', 'a', encoding='utf-8')
47307db96d56Sopenharmony_ci        self.assertEqual(handler.stream.mode, expected.stream.mode)
47317db96d56Sopenharmony_ci        self.assertEqual(handler.stream.name, expected.stream.name)
47327db96d56Sopenharmony_ci        self.addCleanup(cleanup, handler, expected, 'test.log')
47337db96d56Sopenharmony_ci
47347db96d56Sopenharmony_ci    def test_filemode(self):
47357db96d56Sopenharmony_ci
47367db96d56Sopenharmony_ci        def cleanup(h1, h2, fn):
47377db96d56Sopenharmony_ci            h1.close()
47387db96d56Sopenharmony_ci            h2.close()
47397db96d56Sopenharmony_ci            os.remove(fn)
47407db96d56Sopenharmony_ci
47417db96d56Sopenharmony_ci        logging.basicConfig(filename='test.log', filemode='wb')
47427db96d56Sopenharmony_ci
47437db96d56Sopenharmony_ci        handler = logging.root.handlers[0]
47447db96d56Sopenharmony_ci        expected = logging.FileHandler('test.log', 'wb')
47457db96d56Sopenharmony_ci        self.assertEqual(handler.stream.mode, expected.stream.mode)
47467db96d56Sopenharmony_ci        self.addCleanup(cleanup, handler, expected, 'test.log')
47477db96d56Sopenharmony_ci
47487db96d56Sopenharmony_ci    def test_stream(self):
47497db96d56Sopenharmony_ci        stream = io.StringIO()
47507db96d56Sopenharmony_ci        self.addCleanup(stream.close)
47517db96d56Sopenharmony_ci        logging.basicConfig(stream=stream)
47527db96d56Sopenharmony_ci
47537db96d56Sopenharmony_ci        self.assertEqual(len(logging.root.handlers), 1)
47547db96d56Sopenharmony_ci        handler = logging.root.handlers[0]
47557db96d56Sopenharmony_ci        self.assertIsInstance(handler, logging.StreamHandler)
47567db96d56Sopenharmony_ci        self.assertEqual(handler.stream, stream)
47577db96d56Sopenharmony_ci
47587db96d56Sopenharmony_ci    def test_format(self):
47597db96d56Sopenharmony_ci        logging.basicConfig(format='%(asctime)s - %(message)s')
47607db96d56Sopenharmony_ci
47617db96d56Sopenharmony_ci        formatter = logging.root.handlers[0].formatter
47627db96d56Sopenharmony_ci        self.assertEqual(formatter._style._fmt, '%(asctime)s - %(message)s')
47637db96d56Sopenharmony_ci
47647db96d56Sopenharmony_ci    def test_datefmt(self):
47657db96d56Sopenharmony_ci        logging.basicConfig(datefmt='bar')
47667db96d56Sopenharmony_ci
47677db96d56Sopenharmony_ci        formatter = logging.root.handlers[0].formatter
47687db96d56Sopenharmony_ci        self.assertEqual(formatter.datefmt, 'bar')
47697db96d56Sopenharmony_ci
47707db96d56Sopenharmony_ci    def test_style(self):
47717db96d56Sopenharmony_ci        logging.basicConfig(style='$')
47727db96d56Sopenharmony_ci
47737db96d56Sopenharmony_ci        formatter = logging.root.handlers[0].formatter
47747db96d56Sopenharmony_ci        self.assertIsInstance(formatter._style, logging.StringTemplateStyle)
47757db96d56Sopenharmony_ci
47767db96d56Sopenharmony_ci    def test_level(self):
47777db96d56Sopenharmony_ci        old_level = logging.root.level
47787db96d56Sopenharmony_ci        self.addCleanup(logging.root.setLevel, old_level)
47797db96d56Sopenharmony_ci
47807db96d56Sopenharmony_ci        logging.basicConfig(level=57)
47817db96d56Sopenharmony_ci        self.assertEqual(logging.root.level, 57)
47827db96d56Sopenharmony_ci        # Test that second call has no effect
47837db96d56Sopenharmony_ci        logging.basicConfig(level=58)
47847db96d56Sopenharmony_ci        self.assertEqual(logging.root.level, 57)
47857db96d56Sopenharmony_ci
47867db96d56Sopenharmony_ci    def test_incompatible(self):
47877db96d56Sopenharmony_ci        assertRaises = self.assertRaises
47887db96d56Sopenharmony_ci        handlers = [logging.StreamHandler()]
47897db96d56Sopenharmony_ci        stream = sys.stderr
47907db96d56Sopenharmony_ci        assertRaises(ValueError, logging.basicConfig, filename='test.log',
47917db96d56Sopenharmony_ci                                                      stream=stream)
47927db96d56Sopenharmony_ci        assertRaises(ValueError, logging.basicConfig, filename='test.log',
47937db96d56Sopenharmony_ci                                                      handlers=handlers)
47947db96d56Sopenharmony_ci        assertRaises(ValueError, logging.basicConfig, stream=stream,
47957db96d56Sopenharmony_ci                                                      handlers=handlers)
47967db96d56Sopenharmony_ci        # Issue 23207: test for invalid kwargs
47977db96d56Sopenharmony_ci        assertRaises(ValueError, logging.basicConfig, loglevel=logging.INFO)
47987db96d56Sopenharmony_ci        # Should pop both filename and filemode even if filename is None
47997db96d56Sopenharmony_ci        logging.basicConfig(filename=None, filemode='a')
48007db96d56Sopenharmony_ci
48017db96d56Sopenharmony_ci    def test_handlers(self):
48027db96d56Sopenharmony_ci        handlers = [
48037db96d56Sopenharmony_ci            logging.StreamHandler(),
48047db96d56Sopenharmony_ci            logging.StreamHandler(sys.stdout),
48057db96d56Sopenharmony_ci            logging.StreamHandler(),
48067db96d56Sopenharmony_ci        ]
48077db96d56Sopenharmony_ci        f = logging.Formatter()
48087db96d56Sopenharmony_ci        handlers[2].setFormatter(f)
48097db96d56Sopenharmony_ci        logging.basicConfig(handlers=handlers)
48107db96d56Sopenharmony_ci        self.assertIs(handlers[0], logging.root.handlers[0])
48117db96d56Sopenharmony_ci        self.assertIs(handlers[1], logging.root.handlers[1])
48127db96d56Sopenharmony_ci        self.assertIs(handlers[2], logging.root.handlers[2])
48137db96d56Sopenharmony_ci        self.assertIsNotNone(handlers[0].formatter)
48147db96d56Sopenharmony_ci        self.assertIsNotNone(handlers[1].formatter)
48157db96d56Sopenharmony_ci        self.assertIs(handlers[2].formatter, f)
48167db96d56Sopenharmony_ci        self.assertIs(handlers[0].formatter, handlers[1].formatter)
48177db96d56Sopenharmony_ci
48187db96d56Sopenharmony_ci    def test_force(self):
48197db96d56Sopenharmony_ci        old_string_io = io.StringIO()
48207db96d56Sopenharmony_ci        new_string_io = io.StringIO()
48217db96d56Sopenharmony_ci        old_handlers = [logging.StreamHandler(old_string_io)]
48227db96d56Sopenharmony_ci        new_handlers = [logging.StreamHandler(new_string_io)]
48237db96d56Sopenharmony_ci        logging.basicConfig(level=logging.WARNING, handlers=old_handlers)
48247db96d56Sopenharmony_ci        logging.warning('warn')
48257db96d56Sopenharmony_ci        logging.info('info')
48267db96d56Sopenharmony_ci        logging.debug('debug')
48277db96d56Sopenharmony_ci        self.assertEqual(len(logging.root.handlers), 1)
48287db96d56Sopenharmony_ci        logging.basicConfig(level=logging.INFO, handlers=new_handlers,
48297db96d56Sopenharmony_ci                            force=True)
48307db96d56Sopenharmony_ci        logging.warning('warn')
48317db96d56Sopenharmony_ci        logging.info('info')
48327db96d56Sopenharmony_ci        logging.debug('debug')
48337db96d56Sopenharmony_ci        self.assertEqual(len(logging.root.handlers), 1)
48347db96d56Sopenharmony_ci        self.assertEqual(old_string_io.getvalue().strip(),
48357db96d56Sopenharmony_ci                         'WARNING:root:warn')
48367db96d56Sopenharmony_ci        self.assertEqual(new_string_io.getvalue().strip(),
48377db96d56Sopenharmony_ci                         'WARNING:root:warn\nINFO:root:info')
48387db96d56Sopenharmony_ci
48397db96d56Sopenharmony_ci    def test_encoding(self):
48407db96d56Sopenharmony_ci        try:
48417db96d56Sopenharmony_ci            encoding = 'utf-8'
48427db96d56Sopenharmony_ci            logging.basicConfig(filename='test.log', encoding=encoding,
48437db96d56Sopenharmony_ci                                errors='strict',
48447db96d56Sopenharmony_ci                                format='%(message)s', level=logging.DEBUG)
48457db96d56Sopenharmony_ci
48467db96d56Sopenharmony_ci            self.assertEqual(len(logging.root.handlers), 1)
48477db96d56Sopenharmony_ci            handler = logging.root.handlers[0]
48487db96d56Sopenharmony_ci            self.assertIsInstance(handler, logging.FileHandler)
48497db96d56Sopenharmony_ci            self.assertEqual(handler.encoding, encoding)
48507db96d56Sopenharmony_ci            logging.debug('The Øresund Bridge joins Copenhagen to Malmö')
48517db96d56Sopenharmony_ci        finally:
48527db96d56Sopenharmony_ci            handler.close()
48537db96d56Sopenharmony_ci            with open('test.log', encoding='utf-8') as f:
48547db96d56Sopenharmony_ci                data = f.read().strip()
48557db96d56Sopenharmony_ci            os.remove('test.log')
48567db96d56Sopenharmony_ci            self.assertEqual(data,
48577db96d56Sopenharmony_ci                             'The Øresund Bridge joins Copenhagen to Malmö')
48587db96d56Sopenharmony_ci
48597db96d56Sopenharmony_ci    def test_encoding_errors(self):
48607db96d56Sopenharmony_ci        try:
48617db96d56Sopenharmony_ci            encoding = 'ascii'
48627db96d56Sopenharmony_ci            logging.basicConfig(filename='test.log', encoding=encoding,
48637db96d56Sopenharmony_ci                                errors='ignore',
48647db96d56Sopenharmony_ci                                format='%(message)s', level=logging.DEBUG)
48657db96d56Sopenharmony_ci
48667db96d56Sopenharmony_ci            self.assertEqual(len(logging.root.handlers), 1)
48677db96d56Sopenharmony_ci            handler = logging.root.handlers[0]
48687db96d56Sopenharmony_ci            self.assertIsInstance(handler, logging.FileHandler)
48697db96d56Sopenharmony_ci            self.assertEqual(handler.encoding, encoding)
48707db96d56Sopenharmony_ci            logging.debug('The Øresund Bridge joins Copenhagen to Malmö')
48717db96d56Sopenharmony_ci        finally:
48727db96d56Sopenharmony_ci            handler.close()
48737db96d56Sopenharmony_ci            with open('test.log', encoding='utf-8') as f:
48747db96d56Sopenharmony_ci                data = f.read().strip()
48757db96d56Sopenharmony_ci            os.remove('test.log')
48767db96d56Sopenharmony_ci            self.assertEqual(data, 'The resund Bridge joins Copenhagen to Malm')
48777db96d56Sopenharmony_ci
48787db96d56Sopenharmony_ci    def test_encoding_errors_default(self):
48797db96d56Sopenharmony_ci        try:
48807db96d56Sopenharmony_ci            encoding = 'ascii'
48817db96d56Sopenharmony_ci            logging.basicConfig(filename='test.log', encoding=encoding,
48827db96d56Sopenharmony_ci                                format='%(message)s', level=logging.DEBUG)
48837db96d56Sopenharmony_ci
48847db96d56Sopenharmony_ci            self.assertEqual(len(logging.root.handlers), 1)
48857db96d56Sopenharmony_ci            handler = logging.root.handlers[0]
48867db96d56Sopenharmony_ci            self.assertIsInstance(handler, logging.FileHandler)
48877db96d56Sopenharmony_ci            self.assertEqual(handler.encoding, encoding)
48887db96d56Sopenharmony_ci            self.assertEqual(handler.errors, 'backslashreplace')
48897db96d56Sopenharmony_ci            logging.debug('�: ☃️: The Øresund Bridge joins Copenhagen to Malmö')
48907db96d56Sopenharmony_ci        finally:
48917db96d56Sopenharmony_ci            handler.close()
48927db96d56Sopenharmony_ci            with open('test.log', encoding='utf-8') as f:
48937db96d56Sopenharmony_ci                data = f.read().strip()
48947db96d56Sopenharmony_ci            os.remove('test.log')
48957db96d56Sopenharmony_ci            self.assertEqual(data, r'\U0001f602: \u2603\ufe0f: The \xd8resund '
48967db96d56Sopenharmony_ci                                   r'Bridge joins Copenhagen to Malm\xf6')
48977db96d56Sopenharmony_ci
48987db96d56Sopenharmony_ci    def test_encoding_errors_none(self):
48997db96d56Sopenharmony_ci        # Specifying None should behave as 'strict'
49007db96d56Sopenharmony_ci        try:
49017db96d56Sopenharmony_ci            encoding = 'ascii'
49027db96d56Sopenharmony_ci            logging.basicConfig(filename='test.log', encoding=encoding,
49037db96d56Sopenharmony_ci                                errors=None,
49047db96d56Sopenharmony_ci                                format='%(message)s', level=logging.DEBUG)
49057db96d56Sopenharmony_ci
49067db96d56Sopenharmony_ci            self.assertEqual(len(logging.root.handlers), 1)
49077db96d56Sopenharmony_ci            handler = logging.root.handlers[0]
49087db96d56Sopenharmony_ci            self.assertIsInstance(handler, logging.FileHandler)
49097db96d56Sopenharmony_ci            self.assertEqual(handler.encoding, encoding)
49107db96d56Sopenharmony_ci            self.assertIsNone(handler.errors)
49117db96d56Sopenharmony_ci
49127db96d56Sopenharmony_ci            message = []
49137db96d56Sopenharmony_ci
49147db96d56Sopenharmony_ci            def dummy_handle_error(record):
49157db96d56Sopenharmony_ci                _, v, _ = sys.exc_info()
49167db96d56Sopenharmony_ci                message.append(str(v))
49177db96d56Sopenharmony_ci
49187db96d56Sopenharmony_ci            handler.handleError = dummy_handle_error
49197db96d56Sopenharmony_ci            logging.debug('The Øresund Bridge joins Copenhagen to Malmö')
49207db96d56Sopenharmony_ci            self.assertTrue(message)
49217db96d56Sopenharmony_ci            self.assertIn("'ascii' codec can't encode "
49227db96d56Sopenharmony_ci                          "character '\\xd8' in position 4:", message[0])
49237db96d56Sopenharmony_ci        finally:
49247db96d56Sopenharmony_ci            handler.close()
49257db96d56Sopenharmony_ci            with open('test.log', encoding='utf-8') as f:
49267db96d56Sopenharmony_ci                data = f.read().strip()
49277db96d56Sopenharmony_ci            os.remove('test.log')
49287db96d56Sopenharmony_ci            # didn't write anything due to the encoding error
49297db96d56Sopenharmony_ci            self.assertEqual(data, r'')
49307db96d56Sopenharmony_ci
49317db96d56Sopenharmony_ci
49327db96d56Sopenharmony_ci    def _test_log(self, method, level=None):
49337db96d56Sopenharmony_ci        # logging.root has no handlers so basicConfig should be called
49347db96d56Sopenharmony_ci        called = []
49357db96d56Sopenharmony_ci
49367db96d56Sopenharmony_ci        old_basic_config = logging.basicConfig
49377db96d56Sopenharmony_ci        def my_basic_config(*a, **kw):
49387db96d56Sopenharmony_ci            old_basic_config()
49397db96d56Sopenharmony_ci            old_level = logging.root.level
49407db96d56Sopenharmony_ci            logging.root.setLevel(100)  # avoid having messages in stderr
49417db96d56Sopenharmony_ci            self.addCleanup(logging.root.setLevel, old_level)
49427db96d56Sopenharmony_ci            called.append((a, kw))
49437db96d56Sopenharmony_ci
49447db96d56Sopenharmony_ci        support.patch(self, logging, 'basicConfig', my_basic_config)
49457db96d56Sopenharmony_ci
49467db96d56Sopenharmony_ci        log_method = getattr(logging, method)
49477db96d56Sopenharmony_ci        if level is not None:
49487db96d56Sopenharmony_ci            log_method(level, "test me")
49497db96d56Sopenharmony_ci        else:
49507db96d56Sopenharmony_ci            log_method("test me")
49517db96d56Sopenharmony_ci
49527db96d56Sopenharmony_ci        # basicConfig was called with no arguments
49537db96d56Sopenharmony_ci        self.assertEqual(called, [((), {})])
49547db96d56Sopenharmony_ci
49557db96d56Sopenharmony_ci    def test_log(self):
49567db96d56Sopenharmony_ci        self._test_log('log', logging.WARNING)
49577db96d56Sopenharmony_ci
49587db96d56Sopenharmony_ci    def test_debug(self):
49597db96d56Sopenharmony_ci        self._test_log('debug')
49607db96d56Sopenharmony_ci
49617db96d56Sopenharmony_ci    def test_info(self):
49627db96d56Sopenharmony_ci        self._test_log('info')
49637db96d56Sopenharmony_ci
49647db96d56Sopenharmony_ci    def test_warning(self):
49657db96d56Sopenharmony_ci        self._test_log('warning')
49667db96d56Sopenharmony_ci
49677db96d56Sopenharmony_ci    def test_error(self):
49687db96d56Sopenharmony_ci        self._test_log('error')
49697db96d56Sopenharmony_ci
49707db96d56Sopenharmony_ci    def test_critical(self):
49717db96d56Sopenharmony_ci        self._test_log('critical')
49727db96d56Sopenharmony_ci
49737db96d56Sopenharmony_ci
49747db96d56Sopenharmony_ciclass LoggerAdapterTest(unittest.TestCase):
49757db96d56Sopenharmony_ci    def setUp(self):
49767db96d56Sopenharmony_ci        super(LoggerAdapterTest, self).setUp()
49777db96d56Sopenharmony_ci        old_handler_list = logging._handlerList[:]
49787db96d56Sopenharmony_ci
49797db96d56Sopenharmony_ci        self.recording = RecordingHandler()
49807db96d56Sopenharmony_ci        self.logger = logging.root
49817db96d56Sopenharmony_ci        self.logger.addHandler(self.recording)
49827db96d56Sopenharmony_ci        self.addCleanup(self.logger.removeHandler, self.recording)
49837db96d56Sopenharmony_ci        self.addCleanup(self.recording.close)
49847db96d56Sopenharmony_ci
49857db96d56Sopenharmony_ci        def cleanup():
49867db96d56Sopenharmony_ci            logging._handlerList[:] = old_handler_list
49877db96d56Sopenharmony_ci
49887db96d56Sopenharmony_ci        self.addCleanup(cleanup)
49897db96d56Sopenharmony_ci        self.addCleanup(logging.shutdown)
49907db96d56Sopenharmony_ci        self.adapter = logging.LoggerAdapter(logger=self.logger, extra=None)
49917db96d56Sopenharmony_ci
49927db96d56Sopenharmony_ci    def test_exception(self):
49937db96d56Sopenharmony_ci        msg = 'testing exception: %r'
49947db96d56Sopenharmony_ci        exc = None
49957db96d56Sopenharmony_ci        try:
49967db96d56Sopenharmony_ci            1 / 0
49977db96d56Sopenharmony_ci        except ZeroDivisionError as e:
49987db96d56Sopenharmony_ci            exc = e
49997db96d56Sopenharmony_ci            self.adapter.exception(msg, self.recording)
50007db96d56Sopenharmony_ci
50017db96d56Sopenharmony_ci        self.assertEqual(len(self.recording.records), 1)
50027db96d56Sopenharmony_ci        record = self.recording.records[0]
50037db96d56Sopenharmony_ci        self.assertEqual(record.levelno, logging.ERROR)
50047db96d56Sopenharmony_ci        self.assertEqual(record.msg, msg)
50057db96d56Sopenharmony_ci        self.assertEqual(record.args, (self.recording,))
50067db96d56Sopenharmony_ci        self.assertEqual(record.exc_info,
50077db96d56Sopenharmony_ci                         (exc.__class__, exc, exc.__traceback__))
50087db96d56Sopenharmony_ci
50097db96d56Sopenharmony_ci    def test_exception_excinfo(self):
50107db96d56Sopenharmony_ci        try:
50117db96d56Sopenharmony_ci            1 / 0
50127db96d56Sopenharmony_ci        except ZeroDivisionError as e:
50137db96d56Sopenharmony_ci            exc = e
50147db96d56Sopenharmony_ci
50157db96d56Sopenharmony_ci        self.adapter.exception('exc_info test', exc_info=exc)
50167db96d56Sopenharmony_ci
50177db96d56Sopenharmony_ci        self.assertEqual(len(self.recording.records), 1)
50187db96d56Sopenharmony_ci        record = self.recording.records[0]
50197db96d56Sopenharmony_ci        self.assertEqual(record.exc_info,
50207db96d56Sopenharmony_ci                         (exc.__class__, exc, exc.__traceback__))
50217db96d56Sopenharmony_ci
50227db96d56Sopenharmony_ci    def test_critical(self):
50237db96d56Sopenharmony_ci        msg = 'critical test! %r'
50247db96d56Sopenharmony_ci        self.adapter.critical(msg, self.recording)
50257db96d56Sopenharmony_ci
50267db96d56Sopenharmony_ci        self.assertEqual(len(self.recording.records), 1)
50277db96d56Sopenharmony_ci        record = self.recording.records[0]
50287db96d56Sopenharmony_ci        self.assertEqual(record.levelno, logging.CRITICAL)
50297db96d56Sopenharmony_ci        self.assertEqual(record.msg, msg)
50307db96d56Sopenharmony_ci        self.assertEqual(record.args, (self.recording,))
50317db96d56Sopenharmony_ci
50327db96d56Sopenharmony_ci    def test_is_enabled_for(self):
50337db96d56Sopenharmony_ci        old_disable = self.adapter.logger.manager.disable
50347db96d56Sopenharmony_ci        self.adapter.logger.manager.disable = 33
50357db96d56Sopenharmony_ci        self.addCleanup(setattr, self.adapter.logger.manager, 'disable',
50367db96d56Sopenharmony_ci                        old_disable)
50377db96d56Sopenharmony_ci        self.assertFalse(self.adapter.isEnabledFor(32))
50387db96d56Sopenharmony_ci
50397db96d56Sopenharmony_ci    def test_has_handlers(self):
50407db96d56Sopenharmony_ci        self.assertTrue(self.adapter.hasHandlers())
50417db96d56Sopenharmony_ci
50427db96d56Sopenharmony_ci        for handler in self.logger.handlers:
50437db96d56Sopenharmony_ci            self.logger.removeHandler(handler)
50447db96d56Sopenharmony_ci
50457db96d56Sopenharmony_ci        self.assertFalse(self.logger.hasHandlers())
50467db96d56Sopenharmony_ci        self.assertFalse(self.adapter.hasHandlers())
50477db96d56Sopenharmony_ci
50487db96d56Sopenharmony_ci    def test_nested(self):
50497db96d56Sopenharmony_ci        class Adapter(logging.LoggerAdapter):
50507db96d56Sopenharmony_ci            prefix = 'Adapter'
50517db96d56Sopenharmony_ci
50527db96d56Sopenharmony_ci            def process(self, msg, kwargs):
50537db96d56Sopenharmony_ci                return f"{self.prefix} {msg}", kwargs
50547db96d56Sopenharmony_ci
50557db96d56Sopenharmony_ci        msg = 'Adapters can be nested, yo.'
50567db96d56Sopenharmony_ci        adapter = Adapter(logger=self.logger, extra=None)
50577db96d56Sopenharmony_ci        adapter_adapter = Adapter(logger=adapter, extra=None)
50587db96d56Sopenharmony_ci        adapter_adapter.prefix = 'AdapterAdapter'
50597db96d56Sopenharmony_ci        self.assertEqual(repr(adapter), repr(adapter_adapter))
50607db96d56Sopenharmony_ci        adapter_adapter.log(logging.CRITICAL, msg, self.recording)
50617db96d56Sopenharmony_ci        self.assertEqual(len(self.recording.records), 1)
50627db96d56Sopenharmony_ci        record = self.recording.records[0]
50637db96d56Sopenharmony_ci        self.assertEqual(record.levelno, logging.CRITICAL)
50647db96d56Sopenharmony_ci        self.assertEqual(record.msg, f"Adapter AdapterAdapter {msg}")
50657db96d56Sopenharmony_ci        self.assertEqual(record.args, (self.recording,))
50667db96d56Sopenharmony_ci        orig_manager = adapter_adapter.manager
50677db96d56Sopenharmony_ci        self.assertIs(adapter.manager, orig_manager)
50687db96d56Sopenharmony_ci        self.assertIs(self.logger.manager, orig_manager)
50697db96d56Sopenharmony_ci        temp_manager = object()
50707db96d56Sopenharmony_ci        try:
50717db96d56Sopenharmony_ci            adapter_adapter.manager = temp_manager
50727db96d56Sopenharmony_ci            self.assertIs(adapter_adapter.manager, temp_manager)
50737db96d56Sopenharmony_ci            self.assertIs(adapter.manager, temp_manager)
50747db96d56Sopenharmony_ci            self.assertIs(self.logger.manager, temp_manager)
50757db96d56Sopenharmony_ci        finally:
50767db96d56Sopenharmony_ci            adapter_adapter.manager = orig_manager
50777db96d56Sopenharmony_ci        self.assertIs(adapter_adapter.manager, orig_manager)
50787db96d56Sopenharmony_ci        self.assertIs(adapter.manager, orig_manager)
50797db96d56Sopenharmony_ci        self.assertIs(self.logger.manager, orig_manager)
50807db96d56Sopenharmony_ci
50817db96d56Sopenharmony_ci
50827db96d56Sopenharmony_ciclass LoggerTest(BaseTest, AssertErrorMessage):
50837db96d56Sopenharmony_ci
50847db96d56Sopenharmony_ci    def setUp(self):
50857db96d56Sopenharmony_ci        super(LoggerTest, self).setUp()
50867db96d56Sopenharmony_ci        self.recording = RecordingHandler()
50877db96d56Sopenharmony_ci        self.logger = logging.Logger(name='blah')
50887db96d56Sopenharmony_ci        self.logger.addHandler(self.recording)
50897db96d56Sopenharmony_ci        self.addCleanup(self.logger.removeHandler, self.recording)
50907db96d56Sopenharmony_ci        self.addCleanup(self.recording.close)
50917db96d56Sopenharmony_ci        self.addCleanup(logging.shutdown)
50927db96d56Sopenharmony_ci
50937db96d56Sopenharmony_ci    def test_set_invalid_level(self):
50947db96d56Sopenharmony_ci        self.assert_error_message(
50957db96d56Sopenharmony_ci            TypeError, 'Level not an integer or a valid string: None',
50967db96d56Sopenharmony_ci            self.logger.setLevel, None)
50977db96d56Sopenharmony_ci        self.assert_error_message(
50987db96d56Sopenharmony_ci            TypeError, 'Level not an integer or a valid string: (0, 0)',
50997db96d56Sopenharmony_ci            self.logger.setLevel, (0, 0))
51007db96d56Sopenharmony_ci
51017db96d56Sopenharmony_ci    def test_exception(self):
51027db96d56Sopenharmony_ci        msg = 'testing exception: %r'
51037db96d56Sopenharmony_ci        exc = None
51047db96d56Sopenharmony_ci        try:
51057db96d56Sopenharmony_ci            1 / 0
51067db96d56Sopenharmony_ci        except ZeroDivisionError as e:
51077db96d56Sopenharmony_ci            exc = e
51087db96d56Sopenharmony_ci            self.logger.exception(msg, self.recording)
51097db96d56Sopenharmony_ci
51107db96d56Sopenharmony_ci        self.assertEqual(len(self.recording.records), 1)
51117db96d56Sopenharmony_ci        record = self.recording.records[0]
51127db96d56Sopenharmony_ci        self.assertEqual(record.levelno, logging.ERROR)
51137db96d56Sopenharmony_ci        self.assertEqual(record.msg, msg)
51147db96d56Sopenharmony_ci        self.assertEqual(record.args, (self.recording,))
51157db96d56Sopenharmony_ci        self.assertEqual(record.exc_info,
51167db96d56Sopenharmony_ci                         (exc.__class__, exc, exc.__traceback__))
51177db96d56Sopenharmony_ci
51187db96d56Sopenharmony_ci    def test_log_invalid_level_with_raise(self):
51197db96d56Sopenharmony_ci        with support.swap_attr(logging, 'raiseExceptions', True):
51207db96d56Sopenharmony_ci            self.assertRaises(TypeError, self.logger.log, '10', 'test message')
51217db96d56Sopenharmony_ci
51227db96d56Sopenharmony_ci    def test_log_invalid_level_no_raise(self):
51237db96d56Sopenharmony_ci        with support.swap_attr(logging, 'raiseExceptions', False):
51247db96d56Sopenharmony_ci            self.logger.log('10', 'test message')  # no exception happens
51257db96d56Sopenharmony_ci
51267db96d56Sopenharmony_ci    def test_find_caller_with_stack_info(self):
51277db96d56Sopenharmony_ci        called = []
51287db96d56Sopenharmony_ci        support.patch(self, logging.traceback, 'print_stack',
51297db96d56Sopenharmony_ci                      lambda f, file: called.append(file.getvalue()))
51307db96d56Sopenharmony_ci
51317db96d56Sopenharmony_ci        self.logger.findCaller(stack_info=True)
51327db96d56Sopenharmony_ci
51337db96d56Sopenharmony_ci        self.assertEqual(len(called), 1)
51347db96d56Sopenharmony_ci        self.assertEqual('Stack (most recent call last):\n', called[0])
51357db96d56Sopenharmony_ci
51367db96d56Sopenharmony_ci    def test_find_caller_with_stacklevel(self):
51377db96d56Sopenharmony_ci        the_level = 1
51387db96d56Sopenharmony_ci        trigger = self.logger.warning
51397db96d56Sopenharmony_ci
51407db96d56Sopenharmony_ci        def innermost():
51417db96d56Sopenharmony_ci            trigger('test', stacklevel=the_level)
51427db96d56Sopenharmony_ci
51437db96d56Sopenharmony_ci        def inner():
51447db96d56Sopenharmony_ci            innermost()
51457db96d56Sopenharmony_ci
51467db96d56Sopenharmony_ci        def outer():
51477db96d56Sopenharmony_ci            inner()
51487db96d56Sopenharmony_ci
51497db96d56Sopenharmony_ci        records = self.recording.records
51507db96d56Sopenharmony_ci        outer()
51517db96d56Sopenharmony_ci        self.assertEqual(records[-1].funcName, 'innermost')
51527db96d56Sopenharmony_ci        lineno = records[-1].lineno
51537db96d56Sopenharmony_ci        the_level += 1
51547db96d56Sopenharmony_ci        outer()
51557db96d56Sopenharmony_ci        self.assertEqual(records[-1].funcName, 'inner')
51567db96d56Sopenharmony_ci        self.assertGreater(records[-1].lineno, lineno)
51577db96d56Sopenharmony_ci        lineno = records[-1].lineno
51587db96d56Sopenharmony_ci        the_level += 1
51597db96d56Sopenharmony_ci        outer()
51607db96d56Sopenharmony_ci        self.assertEqual(records[-1].funcName, 'outer')
51617db96d56Sopenharmony_ci        self.assertGreater(records[-1].lineno, lineno)
51627db96d56Sopenharmony_ci        lineno = records[-1].lineno
51637db96d56Sopenharmony_ci        root_logger = logging.getLogger()
51647db96d56Sopenharmony_ci        root_logger.addHandler(self.recording)
51657db96d56Sopenharmony_ci        trigger = logging.warning
51667db96d56Sopenharmony_ci        outer()
51677db96d56Sopenharmony_ci        self.assertEqual(records[-1].funcName, 'outer')
51687db96d56Sopenharmony_ci        root_logger.removeHandler(self.recording)
51697db96d56Sopenharmony_ci        trigger = self.logger.warning
51707db96d56Sopenharmony_ci        the_level += 1
51717db96d56Sopenharmony_ci        outer()
51727db96d56Sopenharmony_ci        self.assertEqual(records[-1].funcName, 'test_find_caller_with_stacklevel')
51737db96d56Sopenharmony_ci        self.assertGreater(records[-1].lineno, lineno)
51747db96d56Sopenharmony_ci
51757db96d56Sopenharmony_ci    def test_make_record_with_extra_overwrite(self):
51767db96d56Sopenharmony_ci        name = 'my record'
51777db96d56Sopenharmony_ci        level = 13
51787db96d56Sopenharmony_ci        fn = lno = msg = args = exc_info = func = sinfo = None
51797db96d56Sopenharmony_ci        rv = logging._logRecordFactory(name, level, fn, lno, msg, args,
51807db96d56Sopenharmony_ci                                       exc_info, func, sinfo)
51817db96d56Sopenharmony_ci
51827db96d56Sopenharmony_ci        for key in ('message', 'asctime') + tuple(rv.__dict__.keys()):
51837db96d56Sopenharmony_ci            extra = {key: 'some value'}
51847db96d56Sopenharmony_ci            self.assertRaises(KeyError, self.logger.makeRecord, name, level,
51857db96d56Sopenharmony_ci                              fn, lno, msg, args, exc_info,
51867db96d56Sopenharmony_ci                              extra=extra, sinfo=sinfo)
51877db96d56Sopenharmony_ci
51887db96d56Sopenharmony_ci    def test_make_record_with_extra_no_overwrite(self):
51897db96d56Sopenharmony_ci        name = 'my record'
51907db96d56Sopenharmony_ci        level = 13
51917db96d56Sopenharmony_ci        fn = lno = msg = args = exc_info = func = sinfo = None
51927db96d56Sopenharmony_ci        extra = {'valid_key': 'some value'}
51937db96d56Sopenharmony_ci        result = self.logger.makeRecord(name, level, fn, lno, msg, args,
51947db96d56Sopenharmony_ci                                        exc_info, extra=extra, sinfo=sinfo)
51957db96d56Sopenharmony_ci        self.assertIn('valid_key', result.__dict__)
51967db96d56Sopenharmony_ci
51977db96d56Sopenharmony_ci    def test_has_handlers(self):
51987db96d56Sopenharmony_ci        self.assertTrue(self.logger.hasHandlers())
51997db96d56Sopenharmony_ci
52007db96d56Sopenharmony_ci        for handler in self.logger.handlers:
52017db96d56Sopenharmony_ci            self.logger.removeHandler(handler)
52027db96d56Sopenharmony_ci        self.assertFalse(self.logger.hasHandlers())
52037db96d56Sopenharmony_ci
52047db96d56Sopenharmony_ci    def test_has_handlers_no_propagate(self):
52057db96d56Sopenharmony_ci        child_logger = logging.getLogger('blah.child')
52067db96d56Sopenharmony_ci        child_logger.propagate = False
52077db96d56Sopenharmony_ci        self.assertFalse(child_logger.hasHandlers())
52087db96d56Sopenharmony_ci
52097db96d56Sopenharmony_ci    def test_is_enabled_for(self):
52107db96d56Sopenharmony_ci        old_disable = self.logger.manager.disable
52117db96d56Sopenharmony_ci        self.logger.manager.disable = 23
52127db96d56Sopenharmony_ci        self.addCleanup(setattr, self.logger.manager, 'disable', old_disable)
52137db96d56Sopenharmony_ci        self.assertFalse(self.logger.isEnabledFor(22))
52147db96d56Sopenharmony_ci
52157db96d56Sopenharmony_ci    def test_is_enabled_for_disabled_logger(self):
52167db96d56Sopenharmony_ci        old_disabled = self.logger.disabled
52177db96d56Sopenharmony_ci        old_disable = self.logger.manager.disable
52187db96d56Sopenharmony_ci
52197db96d56Sopenharmony_ci        self.logger.disabled = True
52207db96d56Sopenharmony_ci        self.logger.manager.disable = 21
52217db96d56Sopenharmony_ci
52227db96d56Sopenharmony_ci        self.addCleanup(setattr, self.logger, 'disabled', old_disabled)
52237db96d56Sopenharmony_ci        self.addCleanup(setattr, self.logger.manager, 'disable', old_disable)
52247db96d56Sopenharmony_ci
52257db96d56Sopenharmony_ci        self.assertFalse(self.logger.isEnabledFor(22))
52267db96d56Sopenharmony_ci
52277db96d56Sopenharmony_ci    def test_root_logger_aliases(self):
52287db96d56Sopenharmony_ci        root = logging.getLogger()
52297db96d56Sopenharmony_ci        self.assertIs(root, logging.root)
52307db96d56Sopenharmony_ci        self.assertIs(root, logging.getLogger(None))
52317db96d56Sopenharmony_ci        self.assertIs(root, logging.getLogger(''))
52327db96d56Sopenharmony_ci        self.assertIs(root, logging.getLogger('root'))
52337db96d56Sopenharmony_ci        self.assertIs(root, logging.getLogger('foo').root)
52347db96d56Sopenharmony_ci        self.assertIs(root, logging.getLogger('foo.bar').root)
52357db96d56Sopenharmony_ci        self.assertIs(root, logging.getLogger('foo').parent)
52367db96d56Sopenharmony_ci
52377db96d56Sopenharmony_ci        self.assertIsNot(root, logging.getLogger('\0'))
52387db96d56Sopenharmony_ci        self.assertIsNot(root, logging.getLogger('foo.bar').parent)
52397db96d56Sopenharmony_ci
52407db96d56Sopenharmony_ci    def test_invalid_names(self):
52417db96d56Sopenharmony_ci        self.assertRaises(TypeError, logging.getLogger, any)
52427db96d56Sopenharmony_ci        self.assertRaises(TypeError, logging.getLogger, b'foo')
52437db96d56Sopenharmony_ci
52447db96d56Sopenharmony_ci    def test_pickling(self):
52457db96d56Sopenharmony_ci        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
52467db96d56Sopenharmony_ci            for name in ('', 'root', 'foo', 'foo.bar', 'baz.bar'):
52477db96d56Sopenharmony_ci                logger = logging.getLogger(name)
52487db96d56Sopenharmony_ci                s = pickle.dumps(logger, proto)
52497db96d56Sopenharmony_ci                unpickled = pickle.loads(s)
52507db96d56Sopenharmony_ci                self.assertIs(unpickled, logger)
52517db96d56Sopenharmony_ci
52527db96d56Sopenharmony_ci    def test_caching(self):
52537db96d56Sopenharmony_ci        root = self.root_logger
52547db96d56Sopenharmony_ci        logger1 = logging.getLogger("abc")
52557db96d56Sopenharmony_ci        logger2 = logging.getLogger("abc.def")
52567db96d56Sopenharmony_ci
52577db96d56Sopenharmony_ci        # Set root logger level and ensure cache is empty
52587db96d56Sopenharmony_ci        root.setLevel(logging.ERROR)
52597db96d56Sopenharmony_ci        self.assertEqual(logger2.getEffectiveLevel(), logging.ERROR)
52607db96d56Sopenharmony_ci        self.assertEqual(logger2._cache, {})
52617db96d56Sopenharmony_ci
52627db96d56Sopenharmony_ci        # Ensure cache is populated and calls are consistent
52637db96d56Sopenharmony_ci        self.assertTrue(logger2.isEnabledFor(logging.ERROR))
52647db96d56Sopenharmony_ci        self.assertFalse(logger2.isEnabledFor(logging.DEBUG))
52657db96d56Sopenharmony_ci        self.assertEqual(logger2._cache, {logging.ERROR: True, logging.DEBUG: False})
52667db96d56Sopenharmony_ci        self.assertEqual(root._cache, {})
52677db96d56Sopenharmony_ci        self.assertTrue(logger2.isEnabledFor(logging.ERROR))
52687db96d56Sopenharmony_ci
52697db96d56Sopenharmony_ci        # Ensure root cache gets populated
52707db96d56Sopenharmony_ci        self.assertEqual(root._cache, {})
52717db96d56Sopenharmony_ci        self.assertTrue(root.isEnabledFor(logging.ERROR))
52727db96d56Sopenharmony_ci        self.assertEqual(root._cache, {logging.ERROR: True})
52737db96d56Sopenharmony_ci
52747db96d56Sopenharmony_ci        # Set parent logger level and ensure caches are emptied
52757db96d56Sopenharmony_ci        logger1.setLevel(logging.CRITICAL)
52767db96d56Sopenharmony_ci        self.assertEqual(logger2.getEffectiveLevel(), logging.CRITICAL)
52777db96d56Sopenharmony_ci        self.assertEqual(logger2._cache, {})
52787db96d56Sopenharmony_ci
52797db96d56Sopenharmony_ci        # Ensure logger2 uses parent logger's effective level
52807db96d56Sopenharmony_ci        self.assertFalse(logger2.isEnabledFor(logging.ERROR))
52817db96d56Sopenharmony_ci
52827db96d56Sopenharmony_ci        # Set level to NOTSET and ensure caches are empty
52837db96d56Sopenharmony_ci        logger2.setLevel(logging.NOTSET)
52847db96d56Sopenharmony_ci        self.assertEqual(logger2.getEffectiveLevel(), logging.CRITICAL)
52857db96d56Sopenharmony_ci        self.assertEqual(logger2._cache, {})
52867db96d56Sopenharmony_ci        self.assertEqual(logger1._cache, {})
52877db96d56Sopenharmony_ci        self.assertEqual(root._cache, {})
52887db96d56Sopenharmony_ci
52897db96d56Sopenharmony_ci        # Verify logger2 follows parent and not root
52907db96d56Sopenharmony_ci        self.assertFalse(logger2.isEnabledFor(logging.ERROR))
52917db96d56Sopenharmony_ci        self.assertTrue(logger2.isEnabledFor(logging.CRITICAL))
52927db96d56Sopenharmony_ci        self.assertFalse(logger1.isEnabledFor(logging.ERROR))
52937db96d56Sopenharmony_ci        self.assertTrue(logger1.isEnabledFor(logging.CRITICAL))
52947db96d56Sopenharmony_ci        self.assertTrue(root.isEnabledFor(logging.ERROR))
52957db96d56Sopenharmony_ci
52967db96d56Sopenharmony_ci        # Disable logging in manager and ensure caches are clear
52977db96d56Sopenharmony_ci        logging.disable()
52987db96d56Sopenharmony_ci        self.assertEqual(logger2.getEffectiveLevel(), logging.CRITICAL)
52997db96d56Sopenharmony_ci        self.assertEqual(logger2._cache, {})
53007db96d56Sopenharmony_ci        self.assertEqual(logger1._cache, {})
53017db96d56Sopenharmony_ci        self.assertEqual(root._cache, {})
53027db96d56Sopenharmony_ci
53037db96d56Sopenharmony_ci        # Ensure no loggers are enabled
53047db96d56Sopenharmony_ci        self.assertFalse(logger1.isEnabledFor(logging.CRITICAL))
53057db96d56Sopenharmony_ci        self.assertFalse(logger2.isEnabledFor(logging.CRITICAL))
53067db96d56Sopenharmony_ci        self.assertFalse(root.isEnabledFor(logging.CRITICAL))
53077db96d56Sopenharmony_ci
53087db96d56Sopenharmony_ci
53097db96d56Sopenharmony_ciclass BaseFileTest(BaseTest):
53107db96d56Sopenharmony_ci    "Base class for handler tests that write log files"
53117db96d56Sopenharmony_ci
53127db96d56Sopenharmony_ci    def setUp(self):
53137db96d56Sopenharmony_ci        BaseTest.setUp(self)
53147db96d56Sopenharmony_ci        fd, self.fn = tempfile.mkstemp(".log", "test_logging-2-")
53157db96d56Sopenharmony_ci        os.close(fd)
53167db96d56Sopenharmony_ci        self.rmfiles = []
53177db96d56Sopenharmony_ci
53187db96d56Sopenharmony_ci    def tearDown(self):
53197db96d56Sopenharmony_ci        for fn in self.rmfiles:
53207db96d56Sopenharmony_ci            os.unlink(fn)
53217db96d56Sopenharmony_ci        if os.path.exists(self.fn):
53227db96d56Sopenharmony_ci            os.unlink(self.fn)
53237db96d56Sopenharmony_ci        BaseTest.tearDown(self)
53247db96d56Sopenharmony_ci
53257db96d56Sopenharmony_ci    def assertLogFile(self, filename):
53267db96d56Sopenharmony_ci        "Assert a log file is there and register it for deletion"
53277db96d56Sopenharmony_ci        self.assertTrue(os.path.exists(filename),
53287db96d56Sopenharmony_ci                        msg="Log file %r does not exist" % filename)
53297db96d56Sopenharmony_ci        self.rmfiles.append(filename)
53307db96d56Sopenharmony_ci
53317db96d56Sopenharmony_ci    def next_rec(self):
53327db96d56Sopenharmony_ci        return logging.LogRecord('n', logging.DEBUG, 'p', 1,
53337db96d56Sopenharmony_ci                                 self.next_message(), None, None, None)
53347db96d56Sopenharmony_ci
53357db96d56Sopenharmony_ciclass FileHandlerTest(BaseFileTest):
53367db96d56Sopenharmony_ci    def test_delay(self):
53377db96d56Sopenharmony_ci        os.unlink(self.fn)
53387db96d56Sopenharmony_ci        fh = logging.FileHandler(self.fn, encoding='utf-8', delay=True)
53397db96d56Sopenharmony_ci        self.assertIsNone(fh.stream)
53407db96d56Sopenharmony_ci        self.assertFalse(os.path.exists(self.fn))
53417db96d56Sopenharmony_ci        fh.handle(logging.makeLogRecord({}))
53427db96d56Sopenharmony_ci        self.assertIsNotNone(fh.stream)
53437db96d56Sopenharmony_ci        self.assertTrue(os.path.exists(self.fn))
53447db96d56Sopenharmony_ci        fh.close()
53457db96d56Sopenharmony_ci
53467db96d56Sopenharmony_ci    def test_emit_after_closing_in_write_mode(self):
53477db96d56Sopenharmony_ci        # Issue #42378
53487db96d56Sopenharmony_ci        os.unlink(self.fn)
53497db96d56Sopenharmony_ci        fh = logging.FileHandler(self.fn, encoding='utf-8', mode='w')
53507db96d56Sopenharmony_ci        fh.setFormatter(logging.Formatter('%(message)s'))
53517db96d56Sopenharmony_ci        fh.emit(self.next_rec())    # '1'
53527db96d56Sopenharmony_ci        fh.close()
53537db96d56Sopenharmony_ci        fh.emit(self.next_rec())    # '2'
53547db96d56Sopenharmony_ci        with open(self.fn) as fp:
53557db96d56Sopenharmony_ci            self.assertEqual(fp.read().strip(), '1')
53567db96d56Sopenharmony_ci
53577db96d56Sopenharmony_ciclass RotatingFileHandlerTest(BaseFileTest):
53587db96d56Sopenharmony_ci    @unittest.skipIf(support.is_wasi, "WASI does not have /dev/null.")
53597db96d56Sopenharmony_ci    def test_should_not_rollover(self):
53607db96d56Sopenharmony_ci        # If maxbytes is zero rollover never occurs
53617db96d56Sopenharmony_ci        rh = logging.handlers.RotatingFileHandler(
53627db96d56Sopenharmony_ci                self.fn, encoding="utf-8", maxBytes=0)
53637db96d56Sopenharmony_ci        self.assertFalse(rh.shouldRollover(None))
53647db96d56Sopenharmony_ci        rh.close()
53657db96d56Sopenharmony_ci        # bpo-45401 - test with special file
53667db96d56Sopenharmony_ci        # We set maxBytes to 1 so that rollover would normally happen, except
53677db96d56Sopenharmony_ci        # for the check for regular files
53687db96d56Sopenharmony_ci        rh = logging.handlers.RotatingFileHandler(
53697db96d56Sopenharmony_ci                os.devnull, encoding="utf-8", maxBytes=1)
53707db96d56Sopenharmony_ci        self.assertFalse(rh.shouldRollover(self.next_rec()))
53717db96d56Sopenharmony_ci        rh.close()
53727db96d56Sopenharmony_ci
53737db96d56Sopenharmony_ci    def test_should_rollover(self):
53747db96d56Sopenharmony_ci        rh = logging.handlers.RotatingFileHandler(self.fn, encoding="utf-8", maxBytes=1)
53757db96d56Sopenharmony_ci        self.assertTrue(rh.shouldRollover(self.next_rec()))
53767db96d56Sopenharmony_ci        rh.close()
53777db96d56Sopenharmony_ci
53787db96d56Sopenharmony_ci    def test_file_created(self):
53797db96d56Sopenharmony_ci        # checks that the file is created and assumes it was created
53807db96d56Sopenharmony_ci        # by us
53817db96d56Sopenharmony_ci        rh = logging.handlers.RotatingFileHandler(self.fn, encoding="utf-8")
53827db96d56Sopenharmony_ci        rh.emit(self.next_rec())
53837db96d56Sopenharmony_ci        self.assertLogFile(self.fn)
53847db96d56Sopenharmony_ci        rh.close()
53857db96d56Sopenharmony_ci
53867db96d56Sopenharmony_ci    def test_rollover_filenames(self):
53877db96d56Sopenharmony_ci        def namer(name):
53887db96d56Sopenharmony_ci            return name + ".test"
53897db96d56Sopenharmony_ci        rh = logging.handlers.RotatingFileHandler(
53907db96d56Sopenharmony_ci            self.fn, encoding="utf-8", backupCount=2, maxBytes=1)
53917db96d56Sopenharmony_ci        rh.namer = namer
53927db96d56Sopenharmony_ci        rh.emit(self.next_rec())
53937db96d56Sopenharmony_ci        self.assertLogFile(self.fn)
53947db96d56Sopenharmony_ci        rh.emit(self.next_rec())
53957db96d56Sopenharmony_ci        self.assertLogFile(namer(self.fn + ".1"))
53967db96d56Sopenharmony_ci        rh.emit(self.next_rec())
53977db96d56Sopenharmony_ci        self.assertLogFile(namer(self.fn + ".2"))
53987db96d56Sopenharmony_ci        self.assertFalse(os.path.exists(namer(self.fn + ".3")))
53997db96d56Sopenharmony_ci        rh.close()
54007db96d56Sopenharmony_ci
54017db96d56Sopenharmony_ci    def test_namer_rotator_inheritance(self):
54027db96d56Sopenharmony_ci        class HandlerWithNamerAndRotator(logging.handlers.RotatingFileHandler):
54037db96d56Sopenharmony_ci            def namer(self, name):
54047db96d56Sopenharmony_ci                return name + ".test"
54057db96d56Sopenharmony_ci
54067db96d56Sopenharmony_ci            def rotator(self, source, dest):
54077db96d56Sopenharmony_ci                if os.path.exists(source):
54087db96d56Sopenharmony_ci                    os.replace(source, dest + ".rotated")
54097db96d56Sopenharmony_ci
54107db96d56Sopenharmony_ci        rh = HandlerWithNamerAndRotator(
54117db96d56Sopenharmony_ci            self.fn, encoding="utf-8", backupCount=2, maxBytes=1)
54127db96d56Sopenharmony_ci        self.assertEqual(rh.namer(self.fn), self.fn + ".test")
54137db96d56Sopenharmony_ci        rh.emit(self.next_rec())
54147db96d56Sopenharmony_ci        self.assertLogFile(self.fn)
54157db96d56Sopenharmony_ci        rh.emit(self.next_rec())
54167db96d56Sopenharmony_ci        self.assertLogFile(rh.namer(self.fn + ".1") + ".rotated")
54177db96d56Sopenharmony_ci        self.assertFalse(os.path.exists(rh.namer(self.fn + ".1")))
54187db96d56Sopenharmony_ci        rh.close()
54197db96d56Sopenharmony_ci
54207db96d56Sopenharmony_ci    @support.requires_zlib()
54217db96d56Sopenharmony_ci    def test_rotator(self):
54227db96d56Sopenharmony_ci        def namer(name):
54237db96d56Sopenharmony_ci            return name + ".gz"
54247db96d56Sopenharmony_ci
54257db96d56Sopenharmony_ci        def rotator(source, dest):
54267db96d56Sopenharmony_ci            with open(source, "rb") as sf:
54277db96d56Sopenharmony_ci                data = sf.read()
54287db96d56Sopenharmony_ci                compressed = zlib.compress(data, 9)
54297db96d56Sopenharmony_ci                with open(dest, "wb") as df:
54307db96d56Sopenharmony_ci                    df.write(compressed)
54317db96d56Sopenharmony_ci            os.remove(source)
54327db96d56Sopenharmony_ci
54337db96d56Sopenharmony_ci        rh = logging.handlers.RotatingFileHandler(
54347db96d56Sopenharmony_ci            self.fn, encoding="utf-8", backupCount=2, maxBytes=1)
54357db96d56Sopenharmony_ci        rh.rotator = rotator
54367db96d56Sopenharmony_ci        rh.namer = namer
54377db96d56Sopenharmony_ci        m1 = self.next_rec()
54387db96d56Sopenharmony_ci        rh.emit(m1)
54397db96d56Sopenharmony_ci        self.assertLogFile(self.fn)
54407db96d56Sopenharmony_ci        m2 = self.next_rec()
54417db96d56Sopenharmony_ci        rh.emit(m2)
54427db96d56Sopenharmony_ci        fn = namer(self.fn + ".1")
54437db96d56Sopenharmony_ci        self.assertLogFile(fn)
54447db96d56Sopenharmony_ci        newline = os.linesep
54457db96d56Sopenharmony_ci        with open(fn, "rb") as f:
54467db96d56Sopenharmony_ci            compressed = f.read()
54477db96d56Sopenharmony_ci            data = zlib.decompress(compressed)
54487db96d56Sopenharmony_ci            self.assertEqual(data.decode("ascii"), m1.msg + newline)
54497db96d56Sopenharmony_ci        rh.emit(self.next_rec())
54507db96d56Sopenharmony_ci        fn = namer(self.fn + ".2")
54517db96d56Sopenharmony_ci        self.assertLogFile(fn)
54527db96d56Sopenharmony_ci        with open(fn, "rb") as f:
54537db96d56Sopenharmony_ci            compressed = f.read()
54547db96d56Sopenharmony_ci            data = zlib.decompress(compressed)
54557db96d56Sopenharmony_ci            self.assertEqual(data.decode("ascii"), m1.msg + newline)
54567db96d56Sopenharmony_ci        rh.emit(self.next_rec())
54577db96d56Sopenharmony_ci        fn = namer(self.fn + ".2")
54587db96d56Sopenharmony_ci        with open(fn, "rb") as f:
54597db96d56Sopenharmony_ci            compressed = f.read()
54607db96d56Sopenharmony_ci            data = zlib.decompress(compressed)
54617db96d56Sopenharmony_ci            self.assertEqual(data.decode("ascii"), m2.msg + newline)
54627db96d56Sopenharmony_ci        self.assertFalse(os.path.exists(namer(self.fn + ".3")))
54637db96d56Sopenharmony_ci        rh.close()
54647db96d56Sopenharmony_ci
54657db96d56Sopenharmony_ciclass TimedRotatingFileHandlerTest(BaseFileTest):
54667db96d56Sopenharmony_ci    @unittest.skipIf(support.is_wasi, "WASI does not have /dev/null.")
54677db96d56Sopenharmony_ci    def test_should_not_rollover(self):
54687db96d56Sopenharmony_ci        # See bpo-45401. Should only ever rollover regular files
54697db96d56Sopenharmony_ci        fh = logging.handlers.TimedRotatingFileHandler(
54707db96d56Sopenharmony_ci                os.devnull, 'S', encoding="utf-8", backupCount=1)
54717db96d56Sopenharmony_ci        time.sleep(1.1)    # a little over a second ...
54727db96d56Sopenharmony_ci        r = logging.makeLogRecord({'msg': 'testing - device file'})
54737db96d56Sopenharmony_ci        self.assertFalse(fh.shouldRollover(r))
54747db96d56Sopenharmony_ci        fh.close()
54757db96d56Sopenharmony_ci
54767db96d56Sopenharmony_ci    # other test methods added below
54777db96d56Sopenharmony_ci    def test_rollover(self):
54787db96d56Sopenharmony_ci        fh = logging.handlers.TimedRotatingFileHandler(
54797db96d56Sopenharmony_ci                self.fn, 'S', encoding="utf-8", backupCount=1)
54807db96d56Sopenharmony_ci        fmt = logging.Formatter('%(asctime)s %(message)s')
54817db96d56Sopenharmony_ci        fh.setFormatter(fmt)
54827db96d56Sopenharmony_ci        r1 = logging.makeLogRecord({'msg': 'testing - initial'})
54837db96d56Sopenharmony_ci        fh.emit(r1)
54847db96d56Sopenharmony_ci        self.assertLogFile(self.fn)
54857db96d56Sopenharmony_ci        time.sleep(1.1)    # a little over a second ...
54867db96d56Sopenharmony_ci        r2 = logging.makeLogRecord({'msg': 'testing - after delay'})
54877db96d56Sopenharmony_ci        fh.emit(r2)
54887db96d56Sopenharmony_ci        fh.close()
54897db96d56Sopenharmony_ci        # At this point, we should have a recent rotated file which we
54907db96d56Sopenharmony_ci        # can test for the existence of. However, in practice, on some
54917db96d56Sopenharmony_ci        # machines which run really slowly, we don't know how far back
54927db96d56Sopenharmony_ci        # in time to go to look for the log file. So, we go back a fair
54937db96d56Sopenharmony_ci        # bit, and stop as soon as we see a rotated file. In theory this
54947db96d56Sopenharmony_ci        # could of course still fail, but the chances are lower.
54957db96d56Sopenharmony_ci        found = False
54967db96d56Sopenharmony_ci        now = datetime.datetime.now()
54977db96d56Sopenharmony_ci        GO_BACK = 5 * 60 # seconds
54987db96d56Sopenharmony_ci        for secs in range(GO_BACK):
54997db96d56Sopenharmony_ci            prev = now - datetime.timedelta(seconds=secs)
55007db96d56Sopenharmony_ci            fn = self.fn + prev.strftime(".%Y-%m-%d_%H-%M-%S")
55017db96d56Sopenharmony_ci            found = os.path.exists(fn)
55027db96d56Sopenharmony_ci            if found:
55037db96d56Sopenharmony_ci                self.rmfiles.append(fn)
55047db96d56Sopenharmony_ci                break
55057db96d56Sopenharmony_ci        msg = 'No rotated files found, went back %d seconds' % GO_BACK
55067db96d56Sopenharmony_ci        if not found:
55077db96d56Sopenharmony_ci            # print additional diagnostics
55087db96d56Sopenharmony_ci            dn, fn = os.path.split(self.fn)
55097db96d56Sopenharmony_ci            files = [f for f in os.listdir(dn) if f.startswith(fn)]
55107db96d56Sopenharmony_ci            print('Test time: %s' % now.strftime("%Y-%m-%d %H-%M-%S"), file=sys.stderr)
55117db96d56Sopenharmony_ci            print('The only matching files are: %s' % files, file=sys.stderr)
55127db96d56Sopenharmony_ci            for f in files:
55137db96d56Sopenharmony_ci                print('Contents of %s:' % f)
55147db96d56Sopenharmony_ci                path = os.path.join(dn, f)
55157db96d56Sopenharmony_ci                with open(path, 'r') as tf:
55167db96d56Sopenharmony_ci                    print(tf.read())
55177db96d56Sopenharmony_ci        self.assertTrue(found, msg=msg)
55187db96d56Sopenharmony_ci
55197db96d56Sopenharmony_ci    def test_invalid(self):
55207db96d56Sopenharmony_ci        assertRaises = self.assertRaises
55217db96d56Sopenharmony_ci        assertRaises(ValueError, logging.handlers.TimedRotatingFileHandler,
55227db96d56Sopenharmony_ci                     self.fn, 'X', encoding="utf-8", delay=True)
55237db96d56Sopenharmony_ci        assertRaises(ValueError, logging.handlers.TimedRotatingFileHandler,
55247db96d56Sopenharmony_ci                     self.fn, 'W', encoding="utf-8", delay=True)
55257db96d56Sopenharmony_ci        assertRaises(ValueError, logging.handlers.TimedRotatingFileHandler,
55267db96d56Sopenharmony_ci                     self.fn, 'W7', encoding="utf-8", delay=True)
55277db96d56Sopenharmony_ci
55287db96d56Sopenharmony_ci    def test_compute_rollover_daily_attime(self):
55297db96d56Sopenharmony_ci        currentTime = 0
55307db96d56Sopenharmony_ci        atTime = datetime.time(12, 0, 0)
55317db96d56Sopenharmony_ci        rh = logging.handlers.TimedRotatingFileHandler(
55327db96d56Sopenharmony_ci            self.fn, encoding="utf-8", when='MIDNIGHT', interval=1, backupCount=0,
55337db96d56Sopenharmony_ci            utc=True, atTime=atTime)
55347db96d56Sopenharmony_ci        try:
55357db96d56Sopenharmony_ci            actual = rh.computeRollover(currentTime)
55367db96d56Sopenharmony_ci            self.assertEqual(actual, currentTime + 12 * 60 * 60)
55377db96d56Sopenharmony_ci
55387db96d56Sopenharmony_ci            actual = rh.computeRollover(currentTime + 13 * 60 * 60)
55397db96d56Sopenharmony_ci            self.assertEqual(actual, currentTime + 36 * 60 * 60)
55407db96d56Sopenharmony_ci        finally:
55417db96d56Sopenharmony_ci            rh.close()
55427db96d56Sopenharmony_ci
55437db96d56Sopenharmony_ci    #@unittest.skipIf(True, 'Temporarily skipped while failures investigated.')
55447db96d56Sopenharmony_ci    def test_compute_rollover_weekly_attime(self):
55457db96d56Sopenharmony_ci        currentTime = int(time.time())
55467db96d56Sopenharmony_ci        today = currentTime - currentTime % 86400
55477db96d56Sopenharmony_ci
55487db96d56Sopenharmony_ci        atTime = datetime.time(12, 0, 0)
55497db96d56Sopenharmony_ci
55507db96d56Sopenharmony_ci        wday = time.gmtime(today).tm_wday
55517db96d56Sopenharmony_ci        for day in range(7):
55527db96d56Sopenharmony_ci            rh = logging.handlers.TimedRotatingFileHandler(
55537db96d56Sopenharmony_ci                self.fn, encoding="utf-8", when='W%d' % day, interval=1, backupCount=0,
55547db96d56Sopenharmony_ci                utc=True, atTime=atTime)
55557db96d56Sopenharmony_ci            try:
55567db96d56Sopenharmony_ci                if wday > day:
55577db96d56Sopenharmony_ci                    # The rollover day has already passed this week, so we
55587db96d56Sopenharmony_ci                    # go over into next week
55597db96d56Sopenharmony_ci                    expected = (7 - wday + day)
55607db96d56Sopenharmony_ci                else:
55617db96d56Sopenharmony_ci                    expected = (day - wday)
55627db96d56Sopenharmony_ci                # At this point expected is in days from now, convert to seconds
55637db96d56Sopenharmony_ci                expected *= 24 * 60 * 60
55647db96d56Sopenharmony_ci                # Add in the rollover time
55657db96d56Sopenharmony_ci                expected += 12 * 60 * 60
55667db96d56Sopenharmony_ci                # Add in adjustment for today
55677db96d56Sopenharmony_ci                expected += today
55687db96d56Sopenharmony_ci                actual = rh.computeRollover(today)
55697db96d56Sopenharmony_ci                if actual != expected:
55707db96d56Sopenharmony_ci                    print('failed in timezone: %d' % time.timezone)
55717db96d56Sopenharmony_ci                    print('local vars: %s' % locals())
55727db96d56Sopenharmony_ci                self.assertEqual(actual, expected)
55737db96d56Sopenharmony_ci                if day == wday:
55747db96d56Sopenharmony_ci                    # goes into following week
55757db96d56Sopenharmony_ci                    expected += 7 * 24 * 60 * 60
55767db96d56Sopenharmony_ci                actual = rh.computeRollover(today + 13 * 60 * 60)
55777db96d56Sopenharmony_ci                if actual != expected:
55787db96d56Sopenharmony_ci                    print('failed in timezone: %d' % time.timezone)
55797db96d56Sopenharmony_ci                    print('local vars: %s' % locals())
55807db96d56Sopenharmony_ci                self.assertEqual(actual, expected)
55817db96d56Sopenharmony_ci            finally:
55827db96d56Sopenharmony_ci                rh.close()
55837db96d56Sopenharmony_ci
55847db96d56Sopenharmony_ci    def test_compute_files_to_delete(self):
55857db96d56Sopenharmony_ci        # See bpo-46063 for background
55867db96d56Sopenharmony_ci        wd = tempfile.mkdtemp(prefix='test_logging_')
55877db96d56Sopenharmony_ci        self.addCleanup(shutil.rmtree, wd)
55887db96d56Sopenharmony_ci        times = []
55897db96d56Sopenharmony_ci        dt = datetime.datetime.now()
55907db96d56Sopenharmony_ci        for i in range(10):
55917db96d56Sopenharmony_ci            times.append(dt.strftime('%Y-%m-%d_%H-%M-%S'))
55927db96d56Sopenharmony_ci            dt += datetime.timedelta(seconds=5)
55937db96d56Sopenharmony_ci        prefixes = ('a.b', 'a.b.c', 'd.e', 'd.e.f')
55947db96d56Sopenharmony_ci        files = []
55957db96d56Sopenharmony_ci        rotators = []
55967db96d56Sopenharmony_ci        for prefix in prefixes:
55977db96d56Sopenharmony_ci            p = os.path.join(wd, '%s.log' % prefix)
55987db96d56Sopenharmony_ci            rotator = logging.handlers.TimedRotatingFileHandler(p, when='s',
55997db96d56Sopenharmony_ci                                                                interval=5,
56007db96d56Sopenharmony_ci                                                                backupCount=7,
56017db96d56Sopenharmony_ci                                                                delay=True)
56027db96d56Sopenharmony_ci            rotators.append(rotator)
56037db96d56Sopenharmony_ci            if prefix.startswith('a.b'):
56047db96d56Sopenharmony_ci                for t in times:
56057db96d56Sopenharmony_ci                    files.append('%s.log.%s' % (prefix, t))
56067db96d56Sopenharmony_ci            else:
56077db96d56Sopenharmony_ci                rotator.namer = lambda name: name.replace('.log', '') + '.log'
56087db96d56Sopenharmony_ci                for t in times:
56097db96d56Sopenharmony_ci                    files.append('%s.%s.log' % (prefix, t))
56107db96d56Sopenharmony_ci        # Create empty files
56117db96d56Sopenharmony_ci        for fn in files:
56127db96d56Sopenharmony_ci            p = os.path.join(wd, fn)
56137db96d56Sopenharmony_ci            with open(p, 'wb') as f:
56147db96d56Sopenharmony_ci                pass
56157db96d56Sopenharmony_ci        # Now the checks that only the correct files are offered up for deletion
56167db96d56Sopenharmony_ci        for i, prefix in enumerate(prefixes):
56177db96d56Sopenharmony_ci            rotator = rotators[i]
56187db96d56Sopenharmony_ci            candidates = rotator.getFilesToDelete()
56197db96d56Sopenharmony_ci            self.assertEqual(len(candidates), 3)
56207db96d56Sopenharmony_ci            if prefix.startswith('a.b'):
56217db96d56Sopenharmony_ci                p = '%s.log.' % prefix
56227db96d56Sopenharmony_ci                for c in candidates:
56237db96d56Sopenharmony_ci                    d, fn = os.path.split(c)
56247db96d56Sopenharmony_ci                    self.assertTrue(fn.startswith(p))
56257db96d56Sopenharmony_ci            else:
56267db96d56Sopenharmony_ci                for c in candidates:
56277db96d56Sopenharmony_ci                    d, fn = os.path.split(c)
56287db96d56Sopenharmony_ci                    self.assertTrue(fn.endswith('.log'))
56297db96d56Sopenharmony_ci                    self.assertTrue(fn.startswith(prefix + '.') and
56307db96d56Sopenharmony_ci                                    fn[len(prefix) + 2].isdigit())
56317db96d56Sopenharmony_ci
56327db96d56Sopenharmony_ci
56337db96d56Sopenharmony_cidef secs(**kw):
56347db96d56Sopenharmony_ci    return datetime.timedelta(**kw) // datetime.timedelta(seconds=1)
56357db96d56Sopenharmony_ci
56367db96d56Sopenharmony_cifor when, exp in (('S', 1),
56377db96d56Sopenharmony_ci                  ('M', 60),
56387db96d56Sopenharmony_ci                  ('H', 60 * 60),
56397db96d56Sopenharmony_ci                  ('D', 60 * 60 * 24),
56407db96d56Sopenharmony_ci                  ('MIDNIGHT', 60 * 60 * 24),
56417db96d56Sopenharmony_ci                  # current time (epoch start) is a Thursday, W0 means Monday
56427db96d56Sopenharmony_ci                  ('W0', secs(days=4, hours=24)),
56437db96d56Sopenharmony_ci                 ):
56447db96d56Sopenharmony_ci    def test_compute_rollover(self, when=when, exp=exp):
56457db96d56Sopenharmony_ci        rh = logging.handlers.TimedRotatingFileHandler(
56467db96d56Sopenharmony_ci            self.fn, encoding="utf-8", when=when, interval=1, backupCount=0, utc=True)
56477db96d56Sopenharmony_ci        currentTime = 0.0
56487db96d56Sopenharmony_ci        actual = rh.computeRollover(currentTime)
56497db96d56Sopenharmony_ci        if exp != actual:
56507db96d56Sopenharmony_ci            # Failures occur on some systems for MIDNIGHT and W0.
56517db96d56Sopenharmony_ci            # Print detailed calculation for MIDNIGHT so we can try to see
56527db96d56Sopenharmony_ci            # what's going on
56537db96d56Sopenharmony_ci            if when == 'MIDNIGHT':
56547db96d56Sopenharmony_ci                try:
56557db96d56Sopenharmony_ci                    if rh.utc:
56567db96d56Sopenharmony_ci                        t = time.gmtime(currentTime)
56577db96d56Sopenharmony_ci                    else:
56587db96d56Sopenharmony_ci                        t = time.localtime(currentTime)
56597db96d56Sopenharmony_ci                    currentHour = t[3]
56607db96d56Sopenharmony_ci                    currentMinute = t[4]
56617db96d56Sopenharmony_ci                    currentSecond = t[5]
56627db96d56Sopenharmony_ci                    # r is the number of seconds left between now and midnight
56637db96d56Sopenharmony_ci                    r = logging.handlers._MIDNIGHT - ((currentHour * 60 +
56647db96d56Sopenharmony_ci                                                       currentMinute) * 60 +
56657db96d56Sopenharmony_ci                            currentSecond)
56667db96d56Sopenharmony_ci                    result = currentTime + r
56677db96d56Sopenharmony_ci                    print('t: %s (%s)' % (t, rh.utc), file=sys.stderr)
56687db96d56Sopenharmony_ci                    print('currentHour: %s' % currentHour, file=sys.stderr)
56697db96d56Sopenharmony_ci                    print('currentMinute: %s' % currentMinute, file=sys.stderr)
56707db96d56Sopenharmony_ci                    print('currentSecond: %s' % currentSecond, file=sys.stderr)
56717db96d56Sopenharmony_ci                    print('r: %s' % r, file=sys.stderr)
56727db96d56Sopenharmony_ci                    print('result: %s' % result, file=sys.stderr)
56737db96d56Sopenharmony_ci                except Exception as e:
56747db96d56Sopenharmony_ci                    print('exception in diagnostic code: %s' % e, file=sys.stderr)
56757db96d56Sopenharmony_ci        self.assertEqual(exp, actual)
56767db96d56Sopenharmony_ci        rh.close()
56777db96d56Sopenharmony_ci    setattr(TimedRotatingFileHandlerTest, "test_compute_rollover_%s" % when, test_compute_rollover)
56787db96d56Sopenharmony_ci
56797db96d56Sopenharmony_ci
56807db96d56Sopenharmony_ci@unittest.skipUnless(win32evtlog, 'win32evtlog/win32evtlogutil/pywintypes required for this test.')
56817db96d56Sopenharmony_ciclass NTEventLogHandlerTest(BaseTest):
56827db96d56Sopenharmony_ci    def test_basic(self):
56837db96d56Sopenharmony_ci        logtype = 'Application'
56847db96d56Sopenharmony_ci        elh = win32evtlog.OpenEventLog(None, logtype)
56857db96d56Sopenharmony_ci        num_recs = win32evtlog.GetNumberOfEventLogRecords(elh)
56867db96d56Sopenharmony_ci
56877db96d56Sopenharmony_ci        try:
56887db96d56Sopenharmony_ci            h = logging.handlers.NTEventLogHandler('test_logging')
56897db96d56Sopenharmony_ci        except pywintypes.error as e:
56907db96d56Sopenharmony_ci            if e.winerror == 5:  # access denied
56917db96d56Sopenharmony_ci                raise unittest.SkipTest('Insufficient privileges to run test')
56927db96d56Sopenharmony_ci            raise
56937db96d56Sopenharmony_ci
56947db96d56Sopenharmony_ci        r = logging.makeLogRecord({'msg': 'Test Log Message'})
56957db96d56Sopenharmony_ci        h.handle(r)
56967db96d56Sopenharmony_ci        h.close()
56977db96d56Sopenharmony_ci        # Now see if the event is recorded
56987db96d56Sopenharmony_ci        self.assertLess(num_recs, win32evtlog.GetNumberOfEventLogRecords(elh))
56997db96d56Sopenharmony_ci        flags = win32evtlog.EVENTLOG_BACKWARDS_READ | \
57007db96d56Sopenharmony_ci                win32evtlog.EVENTLOG_SEQUENTIAL_READ
57017db96d56Sopenharmony_ci        found = False
57027db96d56Sopenharmony_ci        GO_BACK = 100
57037db96d56Sopenharmony_ci        events = win32evtlog.ReadEventLog(elh, flags, GO_BACK)
57047db96d56Sopenharmony_ci        for e in events:
57057db96d56Sopenharmony_ci            if e.SourceName != 'test_logging':
57067db96d56Sopenharmony_ci                continue
57077db96d56Sopenharmony_ci            msg = win32evtlogutil.SafeFormatMessage(e, logtype)
57087db96d56Sopenharmony_ci            if msg != 'Test Log Message\r\n':
57097db96d56Sopenharmony_ci                continue
57107db96d56Sopenharmony_ci            found = True
57117db96d56Sopenharmony_ci            break
57127db96d56Sopenharmony_ci        msg = 'Record not found in event log, went back %d records' % GO_BACK
57137db96d56Sopenharmony_ci        self.assertTrue(found, msg=msg)
57147db96d56Sopenharmony_ci
57157db96d56Sopenharmony_ci
57167db96d56Sopenharmony_ciclass MiscTestCase(unittest.TestCase):
57177db96d56Sopenharmony_ci    def test__all__(self):
57187db96d56Sopenharmony_ci        not_exported = {
57197db96d56Sopenharmony_ci            'logThreads', 'logMultiprocessing', 'logProcesses', 'currentframe',
57207db96d56Sopenharmony_ci            'PercentStyle', 'StrFormatStyle', 'StringTemplateStyle',
57217db96d56Sopenharmony_ci            'Filterer', 'PlaceHolder', 'Manager', 'RootLogger', 'root',
57227db96d56Sopenharmony_ci            'threading'}
57237db96d56Sopenharmony_ci        support.check__all__(self, logging, not_exported=not_exported)
57247db96d56Sopenharmony_ci
57257db96d56Sopenharmony_ci
57267db96d56Sopenharmony_ci# Set the locale to the platform-dependent default.  I have no idea
57277db96d56Sopenharmony_ci# why the test does this, but in any case we save the current locale
57287db96d56Sopenharmony_ci# first and restore it at the end.
57297db96d56Sopenharmony_cidef setUpModule():
57307db96d56Sopenharmony_ci    unittest.enterModuleContext(support.run_with_locale('LC_ALL', ''))
57317db96d56Sopenharmony_ci
57327db96d56Sopenharmony_ci
57337db96d56Sopenharmony_ciif __name__ == "__main__":
57347db96d56Sopenharmony_ci    unittest.main()
5735