|
8 | 8 | import six |
9 | 9 | import pytest |
10 | 10 | import psutil |
11 | | - |
12 | | -import logging.config |
| 11 | +import logging |
| 12 | +import uuid |
13 | 13 |
|
14 | 14 | from contextlib import contextmanager |
15 | 15 |
|
@@ -788,56 +788,95 @@ def test_poll_query_until(self): |
788 | 788 | node.poll_query_until('select true') |
789 | 789 |
|
790 | 790 | def test_logging(self): |
791 | | - # FAIL |
792 | | - logfile = tempfile.NamedTemporaryFile('w', delete=True) |
793 | | - |
794 | | - log_conf = { |
795 | | - 'version': 1, |
796 | | - 'handlers': { |
797 | | - 'file': { |
798 | | - 'class': 'logging.FileHandler', |
799 | | - 'filename': logfile.name, |
800 | | - 'formatter': 'base_format', |
801 | | - 'level': logging.DEBUG, |
802 | | - }, |
803 | | - }, |
804 | | - 'formatters': { |
805 | | - 'base_format': { |
806 | | - 'format': '%(node)-5s: %(message)s', |
807 | | - }, |
808 | | - }, |
809 | | - 'root': { |
810 | | - 'handlers': ('file',), |
811 | | - 'level': 'DEBUG', |
812 | | - }, |
813 | | - } |
814 | | - |
815 | | - logging.config.dictConfig(log_conf) |
816 | | - |
817 | | - with scoped_config(use_python_logging=True): |
818 | | - node_name = 'master' |
819 | | - |
820 | | - with get_remote_node(name=node_name) as master: |
821 | | - master.init().start() |
822 | | - |
823 | | - # execute a dummy query a few times |
824 | | - for i in range(20): |
825 | | - master.execute('select 1') |
826 | | - time.sleep(0.01) |
827 | | - |
828 | | - # let logging worker do the job |
829 | | - time.sleep(0.1) |
830 | | - |
831 | | - # check that master's port is found |
832 | | - with open(logfile.name, 'r') as log: |
833 | | - lines = log.readlines() |
834 | | - assert (any(node_name in s for s in lines)) |
835 | | - |
836 | | - # test logger after stop/start/restart |
837 | | - master.stop() |
838 | | - master.start() |
839 | | - master.restart() |
840 | | - assert (master._logger.is_alive()) |
| 791 | + C_MAX_ATTEMPTS = 50 |
| 792 | + # This name is used for testgres logging, too. |
| 793 | + C_NODE_NAME = "testgres_tests." + __class__.__name__ + "test_logging-master-" + uuid.uuid4().hex |
| 794 | + |
| 795 | + logging.info("Node name is [{0}]".format(C_NODE_NAME)) |
| 796 | + |
| 797 | + with tempfile.NamedTemporaryFile('w', delete=True) as logfile: |
| 798 | + formatter = logging.Formatter(fmt="%(node)-5s: %(message)s") |
| 799 | + handler = logging.FileHandler(filename=logfile.name) |
| 800 | + handler.formatter = formatter |
| 801 | + logger = logging.getLogger(C_NODE_NAME) |
| 802 | + assert logger is not None |
| 803 | + assert len(logger.handlers) == 0 |
| 804 | + |
| 805 | + try: |
| 806 | + # It disables to log on the root level |
| 807 | + logger.propagate = False |
| 808 | + logger.addHandler(handler) |
| 809 | + |
| 810 | + with scoped_config(use_python_logging=True): |
| 811 | + with __class__.helper__get_node(name=C_NODE_NAME) as master: |
| 812 | + logging.info("Master node is initilizing") |
| 813 | + master.init() |
| 814 | + |
| 815 | + logging.info("Master node is starting") |
| 816 | + master.start() |
| 817 | + |
| 818 | + logging.info("Dummy query is executed a few times") |
| 819 | + for _ in range(20): |
| 820 | + master.execute('select 1') |
| 821 | + time.sleep(0.01) |
| 822 | + |
| 823 | + # let logging worker do the job |
| 824 | + time.sleep(0.1) |
| 825 | + |
| 826 | + logging.info("Master node log file is checking") |
| 827 | + nAttempt = 0 |
| 828 | + |
| 829 | + while True: |
| 830 | + assert nAttempt <= C_MAX_ATTEMPTS |
| 831 | + if nAttempt == C_MAX_ATTEMPTS: |
| 832 | + raise Exception("Test failed!") |
| 833 | + |
| 834 | + # let logging worker do the job |
| 835 | + time.sleep(0.1) |
| 836 | + |
| 837 | + nAttempt += 1 |
| 838 | + |
| 839 | + logging.info("Attempt {0}".format(nAttempt)) |
| 840 | + |
| 841 | + # check that master's port is found |
| 842 | + with open(logfile.name, 'r') as log: |
| 843 | + lines = log.readlines() |
| 844 | + |
| 845 | + assert lines is not None |
| 846 | + assert type(lines) == list # noqa: E721 |
| 847 | + |
| 848 | + def LOCAL__test_lines(): |
| 849 | + for s in lines: |
| 850 | + if any(C_NODE_NAME in s for s in lines): |
| 851 | + logging.info("OK. We found the node_name in a line \"{0}\"".format(s)) |
| 852 | + return True |
| 853 | + return False |
| 854 | + |
| 855 | + if LOCAL__test_lines(): |
| 856 | + break |
| 857 | + |
| 858 | + logging.info("Master node log file does not have an expected information.") |
| 859 | + continue |
| 860 | + |
| 861 | + # test logger after stop/start/restart |
| 862 | + logging.info("Master node is stopping...") |
| 863 | + master.stop() |
| 864 | + logging.info("Master node is staring again...") |
| 865 | + master.start() |
| 866 | + logging.info("Master node is restaring...") |
| 867 | + master.restart() |
| 868 | + assert (master._logger.is_alive()) |
| 869 | + finally: |
| 870 | + # It is a hack code to logging cleanup |
| 871 | + logging._acquireLock() |
| 872 | + assert logging.Logger.manager is not None |
| 873 | + assert C_NODE_NAME in logging.Logger.manager.loggerDict.keys() |
| 874 | + logging.Logger.manager.loggerDict.pop(C_NODE_NAME, None) |
| 875 | + assert not (C_NODE_NAME in logging.Logger.manager.loggerDict.keys()) |
| 876 | + assert not (handler in logging._handlers.values()) |
| 877 | + logging._releaseLock() |
| 878 | + # GO HOME! |
| 879 | + return |
841 | 880 |
|
842 | 881 | def test_pgbench(self): |
843 | 882 | __class__.helper__skip_test_if_util_not_exist("pgbench") |
@@ -1184,9 +1223,9 @@ def test_child_process_dies(self): |
1184 | 1223 | break |
1185 | 1224 |
|
1186 | 1225 | @staticmethod |
1187 | | - def helper__get_node(): |
| 1226 | + def helper__get_node(name=None): |
1188 | 1227 | assert __class__.sm_conn_params is not None |
1189 | | - return get_remote_node(conn_params=__class__.sm_conn_params) |
| 1228 | + return get_remote_node(name=name, conn_params=__class__.sm_conn_params) |
1190 | 1229 |
|
1191 | 1230 | @staticmethod |
1192 | 1231 | def helper__restore_envvar(name, prev_value): |
|
0 commit comments