Introduce re-openable log record handler
[ganeti-github.git] / test / ganeti.utils.log_unittest.py
1 #!/usr/bin/python
2 #
3
4 # Copyright (C) 2011 Google Inc.
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 # 02110-1301, USA.
20
21
22 """Script for testing ganeti.utils.log"""
23
24 import os
25 import unittest
26 import logging
27 import tempfile
28
29 from ganeti import constants
30 from ganeti import errors
31 from ganeti import utils
32
33 import testutils
34
35
36 class TestLogHandler(unittest.TestCase):
37 def test(self):
38 tmpfile = tempfile.NamedTemporaryFile()
39
40 handler = utils.log._ReopenableLogHandler(tmpfile.name)
41 handler.setFormatter(logging.Formatter("%(asctime)s: %(message)s"))
42
43 logger = logging.Logger("TestLogger")
44 logger.addHandler(handler)
45 self.assertEqual(len(logger.handlers), 1)
46
47 logger.error("Test message ERROR")
48 logger.info("Test message INFO")
49
50 logger.removeHandler(handler)
51 self.assertFalse(logger.handlers)
52 handler.close()
53
54 self.assertEqual(len(utils.ReadFile(tmpfile.name).splitlines()), 2)
55
56 def testReopen(self):
57 tmpfile = tempfile.NamedTemporaryFile()
58 tmpfile2 = tempfile.NamedTemporaryFile()
59
60 handler = utils.log._ReopenableLogHandler(tmpfile.name)
61
62 self.assertFalse(utils.ReadFile(tmpfile.name))
63 self.assertFalse(utils.ReadFile(tmpfile2.name))
64
65 logger = logging.Logger("TestLoggerReopen")
66 logger.addHandler(handler)
67
68 for _ in range(3):
69 logger.error("Test message ERROR")
70 handler.flush()
71 self.assertEqual(len(utils.ReadFile(tmpfile.name).splitlines()), 3)
72 before_id = utils.GetFileID(tmpfile.name)
73
74 handler.RequestReopen()
75 self.assertTrue(handler._reopen)
76 self.assertTrue(utils.VerifyFileID(utils.GetFileID(tmpfile.name),
77 before_id))
78
79 # Rename only after requesting reopen
80 os.rename(tmpfile.name, tmpfile2.name)
81 assert not os.path.exists(tmpfile.name)
82
83 # Write another message, should reopen
84 for _ in range(4):
85 logger.info("Test message INFO")
86 self.assertFalse(utils.VerifyFileID(utils.GetFileID(tmpfile.name),
87 before_id))
88
89 logger.removeHandler(handler)
90 self.assertFalse(logger.handlers)
91 handler.close()
92
93 self.assertEqual(len(utils.ReadFile(tmpfile.name).splitlines()), 4)
94 self.assertEqual(len(utils.ReadFile(tmpfile2.name).splitlines()), 3)
95
96 def testConsole(self):
97 for (console, check) in [(None, False),
98 (tempfile.NamedTemporaryFile(), True),
99 (self._FailingFile(os.devnull), False)]:
100 # Create a handler which will fail when handling errors
101 cls = utils.log._LogErrorsToConsole(self._FailingHandler)
102
103 # Instantiate handler with file which will fail when writing,
104 # provoking a write to the console
105 handler = cls(console, self._FailingFile(os.devnull))
106
107 logger = logging.Logger("TestLogger")
108 logger.addHandler(handler)
109 self.assertEqual(len(logger.handlers), 1)
110
111 # Provoke write
112 logger.error("Test message ERROR")
113
114 # Take everything apart
115 logger.removeHandler(handler)
116 self.assertFalse(logger.handlers)
117 handler.close()
118
119 if console and check:
120 console.flush()
121
122 # Check console output
123 consout = utils.ReadFile(console.name)
124 self.assertTrue("Cannot log message" in consout)
125 self.assertTrue("Test message ERROR" in consout)
126
127 class _FailingFile(file):
128 def write(self, _):
129 raise Exception
130
131 class _FailingHandler(logging.StreamHandler):
132 def handleError(self, _):
133 raise Exception
134
135
136 if __name__ == "__main__":
137 testutils.GanetiTestProgram()