4 # Copyright (C) 2011 Google Inc.
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.
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.
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
22 """Script for testing ganeti.utils.log"""
30 from ganeti import constants
31 from ganeti import errors
32 from ganeti import utils
37 class TestLogHandler(unittest.TestCase):
39 tmpfile = tempfile.NamedTemporaryFile()
41 handler = utils.log._ReopenableLogHandler(tmpfile.name)
42 handler.setFormatter(logging.Formatter("%(asctime)s: %(message)s"))
44 logger = logging.Logger("TestLogger")
45 logger.addHandler(handler)
46 self.assertEqual(len(logger.handlers), 1)
48 logger.error("Test message ERROR")
49 logger.info("Test message INFO")
51 logger.removeHandler(handler)
52 self.assertFalse(logger.handlers)
55 self.assertEqual(len(utils.ReadFile(tmpfile.name).splitlines()), 2)
58 tmpfile = tempfile.NamedTemporaryFile()
59 tmpfile2 = tempfile.NamedTemporaryFile()
61 handler = utils.log._ReopenableLogHandler(tmpfile.name)
63 self.assertFalse(utils.ReadFile(tmpfile.name))
64 self.assertFalse(utils.ReadFile(tmpfile2.name))
66 logger = logging.Logger("TestLoggerReopen")
67 logger.addHandler(handler)
70 logger.error("Test message ERROR")
72 self.assertEqual(len(utils.ReadFile(tmpfile.name).splitlines()), 3)
73 before_id = utils.GetFileID(tmpfile.name)
75 handler.RequestReopen()
76 self.assertTrue(handler._reopen)
77 self.assertTrue(utils.VerifyFileID(utils.GetFileID(tmpfile.name),
80 # Rename only after requesting reopen
81 os.rename(tmpfile.name, tmpfile2.name)
82 assert not os.path.exists(tmpfile.name)
84 # Write another message, should reopen
86 logger.info("Test message INFO")
87 self.assertFalse(utils.VerifyFileID(utils.GetFileID(tmpfile.name),
90 logger.removeHandler(handler)
91 self.assertFalse(logger.handlers)
94 self.assertEqual(len(utils.ReadFile(tmpfile.name).splitlines()), 4)
95 self.assertEqual(len(utils.ReadFile(tmpfile2.name).splitlines()), 3)
97 def testConsole(self):
98 for (console, check) in [(None, False),
99 (tempfile.NamedTemporaryFile(), True),
100 (self._FailingFile(os.devnull), False)]:
101 # Create a handler which will fail when handling errors
102 cls = utils.log._LogErrorsToConsole(self._FailingHandler)
104 # Instantiate handler with file which will fail when writing,
105 # provoking a write to the console
106 handler = cls(console, self._FailingFile(os.devnull))
108 logger = logging.Logger("TestLogger")
109 logger.addHandler(handler)
110 self.assertEqual(len(logger.handlers), 1)
113 logger.error("Test message ERROR")
115 # Take everything apart
116 logger.removeHandler(handler)
117 self.assertFalse(logger.handlers)
120 if console and check:
123 # Check console output
124 consout = utils.ReadFile(console.name)
125 self.assertTrue("Cannot log message" in consout)
126 self.assertTrue("Test message ERROR" in consout)
128 class _FailingFile(file):
132 class _FailingHandler(logging.StreamHandler):
133 def handleError(self, _):
137 class TestSetupLogging(unittest.TestCase):
139 self.tmpdir = tempfile.mkdtemp()
142 shutil.rmtree(self.tmpdir)
144 def testSimple(self):
145 logfile = utils.PathJoin(self.tmpdir, "basic.log")
146 logger = logging.Logger("TestLogger")
147 self.assertTrue(callable(utils.SetupLogging(logfile, "test",
148 console_logging=False,
149 syslog=constants.SYSLOG_NO,
150 stderr_logging=False,
152 root_logger=logger)))
153 self.assertEqual(utils.ReadFile(logfile), "")
154 logger.error("This is a test")
156 # Ensure SetupLogging used custom logger
157 logging.error("This message should not show up in the test log file")
159 self.assertTrue(utils.ReadFile(logfile).endswith("This is a test\n"))
161 def testReopen(self):
162 logfile = utils.PathJoin(self.tmpdir, "reopen.log")
163 logfile2 = utils.PathJoin(self.tmpdir, "reopen.log.OLD")
164 logger = logging.Logger("TestLogger")
165 reopen_fn = utils.SetupLogging(logfile, "test",
166 console_logging=False,
167 syslog=constants.SYSLOG_NO,
168 stderr_logging=False,
171 self.assertTrue(callable(reopen_fn))
173 self.assertEqual(utils.ReadFile(logfile), "")
174 logger.error("This is a test")
175 self.assertTrue(utils.ReadFile(logfile).endswith("This is a test\n"))
177 os.rename(logfile, logfile2)
178 assert not os.path.exists(logfile)
180 # Notify logger to reopen on the next message
182 assert not os.path.exists(logfile)
184 # Provoke actual reopen
185 logger.error("First message")
187 self.assertTrue(utils.ReadFile(logfile).endswith("First message\n"))
188 self.assertTrue(utils.ReadFile(logfile2).endswith("This is a test\n"))
191 if __name__ == "__main__":
192 testutils.GanetiTestProgram()