|
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