1 # Copyright (c) Twisted Matrix Laboratories.
2 # See LICENSE for details.
4 import os, time, stat, errno
6 from twisted.trial import unittest
7 from twisted.python import logfile, runtime
10 class LogFileTestCase(unittest.TestCase):
12 Test the rotating log file.
16 self.dir = self.mktemp()
18 self.name = "test.log"
19 self.path = os.path.join(self.dir, self.name)
24 Restore back write rights on created paths: if tests modified the
25 rights, that will allow the paths to be removed easily afterwards.
27 os.chmod(self.dir, 0777)
28 if os.path.exists(self.path):
29 os.chmod(self.path, 0777)
32 def testWriting(self):
33 log = logfile.LogFile(self.name, self.dir)
40 f = open(self.path, "r")
41 self.assertEqual(f.read(), "1234567890")
44 def testRotation(self):
45 # this logfile should rotate every 10 bytes
46 log = logfile.LogFile(self.name, self.dir, rotateLength=10)
48 # test automatic rotation
52 self.assert_(os.path.exists("%s.1" % self.path))
53 self.assert_(not os.path.exists("%s.2" % self.path))
55 self.assert_(os.path.exists("%s.1" % self.path))
56 self.assert_(os.path.exists("%s.2" % self.path))
57 self.assert_(not os.path.exists("%s.3" % self.path))
59 self.assert_(not os.path.exists("%s.3" % self.path))
61 # test manual rotation
63 self.assert_(os.path.exists("%s.3" % self.path))
64 self.assert_(not os.path.exists("%s.4" % self.path))
67 self.assertEqual(log.listLogs(), [1, 2, 3])
70 log = logfile.LogFile(self.name, self.dir)
71 log.write("0123456789")
74 log = logfile.LogFile(self.name, self.dir)
75 self.assertEqual(log.size, 10)
76 self.assertEqual(log._file.tell(), log.size)
78 self.assertEqual(log.size, 13)
79 self.assertEqual(log._file.tell(), log.size)
82 self.assertEqual(f.read(), "0123456789abc")
85 def testLogReader(self):
86 log = logfile.LogFile(self.name, self.dir)
94 self.assertEqual(log.listLogs(), [1])
95 reader = log.getCurrentLog()
97 self.assertEqual(reader.readLines(), ["ghi\n"])
98 self.assertEqual(reader.readLines(), [])
100 reader = log.getLog(1)
101 self.assertEqual(reader.readLines(), ["abc\n", "def\n"])
102 self.assertEqual(reader.readLines(), [])
105 # check getting illegal log readers
106 self.assertRaises(ValueError, log.getLog, 2)
107 self.assertRaises(TypeError, log.getLog, "1")
109 # check that log numbers are higher for older logs
111 self.assertEqual(log.listLogs(), [1, 2])
112 reader = log.getLog(1)
114 self.assertEqual(reader.readLines(), ["ghi\n"])
115 self.assertEqual(reader.readLines(), [])
117 reader = log.getLog(2)
118 self.assertEqual(reader.readLines(), ["abc\n", "def\n"])
119 self.assertEqual(reader.readLines(), [])
122 def testModePreservation(self):
124 Check rotated files have same permissions as original.
126 f = open(self.path, "w").close()
127 os.chmod(self.path, 0707)
128 mode = os.stat(self.path)[stat.ST_MODE]
129 log = logfile.LogFile(self.name, self.dir)
132 self.assertEqual(mode, os.stat(self.path)[stat.ST_MODE])
135 def test_noPermission(self):
137 Check it keeps working when permission on dir changes.
139 log = logfile.LogFile(self.name, self.dir)
142 # change permissions so rotation would fail
143 os.chmod(self.dir, 0555)
145 # if this succeeds, chmod doesn't restrict us, so we can't
148 f = open(os.path.join(self.dir,"xxx"), "w")
149 except (OSError, IOError):
155 log.rotate() # this should not fail
161 self.assertEqual(f.tell(), 6)
163 self.assertEqual(f.read(), "abcdef")
167 def test_maxNumberOfLog(self):
169 Test it respect the limit on the number of files when maxRotatedFiles
172 log = logfile.LogFile(self.name, self.dir, rotateLength=10,
176 self.failUnless(os.path.exists("%s.1" % self.path))
179 self.failUnless(os.path.exists("%s.2" % self.path))
182 self.failUnless(os.path.exists("%s.3" % self.path))
183 self.assertEqual(file("%s.3" % self.path).read(), "1" * 11)
186 self.assertEqual(file("%s.3" % self.path).read(), "2" * 11)
187 self.failUnless(not os.path.exists("%s.4" % self.path))
189 def test_fromFullPath(self):
191 Test the fromFullPath method.
193 log1 = logfile.LogFile(self.name, self.dir, 10, defaultMode=0777)
194 log2 = logfile.LogFile.fromFullPath(self.path, 10, defaultMode=0777)
195 self.assertEqual(log1.name, log2.name)
196 self.assertEqual(os.path.abspath(log1.path), log2.path)
197 self.assertEqual(log1.rotateLength, log2.rotateLength)
198 self.assertEqual(log1.defaultMode, log2.defaultMode)
200 def test_defaultPermissions(self):
202 Test the default permission of the log file: if the file exist, it
203 should keep the permission.
205 f = file(self.path, "w")
206 os.chmod(self.path, 0707)
207 currentMode = stat.S_IMODE(os.stat(self.path)[stat.ST_MODE])
209 log1 = logfile.LogFile(self.name, self.dir)
210 self.assertEqual(stat.S_IMODE(os.stat(self.path)[stat.ST_MODE]),
214 def test_specifiedPermissions(self):
216 Test specifying the permissions used on the log file.
218 log1 = logfile.LogFile(self.name, self.dir, defaultMode=0066)
219 mode = stat.S_IMODE(os.stat(self.path)[stat.ST_MODE])
220 if runtime.platform.isWindows():
221 # The only thing we can get here is global read-only
222 self.assertEqual(mode, 0444)
224 self.assertEqual(mode, 0066)
227 def test_reopen(self):
229 L{logfile.LogFile.reopen} allows to rename the currently used file and
230 make L{logfile.LogFile} create a new file.
232 log1 = logfile.LogFile(self.name, self.dir)
234 savePath = os.path.join(self.dir, "save.log")
235 os.rename(self.path, savePath)
240 f = open(self.path, "r")
241 self.assertEqual(f.read(), "hello2")
243 f = open(savePath, "r")
244 self.assertEqual(f.read(), "hello1")
247 if runtime.platform.isWindows():
248 test_reopen.skip = "Can't test reopen on Windows"
251 def test_nonExistentDir(self):
253 Specifying an invalid directory to L{LogFile} raises C{IOError}.
255 e = self.assertRaises(
256 IOError, logfile.LogFile, self.name, 'this_dir_does_not_exist')
257 self.assertEqual(e.errno, errno.ENOENT)
261 class RiggedDailyLogFile(logfile.DailyLogFile):
265 logfile.DailyLogFile._openFile(self)
266 # rig the date to match _clock, not mtime
267 self.lastDate = self.toDate()
269 def toDate(self, *args):
271 return time.gmtime(*args)[:3]
272 return time.gmtime(self._clock)[:3]
274 class DailyLogFileTestCase(unittest.TestCase):
276 Test rotating log file.
280 self.dir = self.mktemp()
281 os.makedirs(self.dir)
282 self.name = "testdaily.log"
283 self.path = os.path.join(self.dir, self.name)
286 def testWriting(self):
287 log = RiggedDailyLogFile(self.name, self.dir)
294 f = open(self.path, "r")
295 self.assertEqual(f.read(), "1234567890")
298 def testRotation(self):
299 # this logfile should rotate every 10 bytes
300 log = RiggedDailyLogFile(self.name, self.dir)
301 days = [(self.path + '.' + log.suffix(day * 86400)) for day in range(3)]
303 # test automatic rotation
304 log._clock = 0.0 # 1970/01/01 00:00.00
306 log._clock = 43200 # 1970/01/01 12:00.00
308 log._clock = 86400 # 1970/01/02 00:00.00
310 self.assert_(os.path.exists(days[0]))
311 self.assert_(not os.path.exists(days[1]))
312 log._clock = 172800 # 1970/01/03 00:00.00
314 self.assert_(os.path.exists(days[0]))
315 self.assert_(os.path.exists(days[1]))
316 self.assert_(not os.path.exists(days[2]))
317 log._clock = 259199 # 1970/01/03 23:59.59
319 self.assert_(not os.path.exists(days[2]))