code review, test case extended;

pull/716/head
sebres 2014-12-02 11:57:43 +01:00
parent 697da99f8f
commit 4dbc77dbbb
2 changed files with 71 additions and 14 deletions

View File

@ -559,7 +559,7 @@ class FileFilter(Filter):
#
# @param path log file path
def addLogPath(self, path, tail = False):
def addLogPath(self, path, tail=False):
if self.containsLogPath(path):
logSys.error(path + " already exists")
else:
@ -655,7 +655,7 @@ class FileFilter(Filter):
# MyTime.time()-self.findTime. When a failure is detected, a FailTicket
# is created and is added to the FailManager.
def getFailures(self, filename, startTime = None):
def getFailures(self, filename, startTime=None):
container = self.getFileContainer(filename)
if container is None:
logSys.error("Unable to get failures in " + filename)
@ -673,14 +673,19 @@ class FileFilter(Filter):
logSys.exception(e)
return False
except OSError, e: # pragma: no cover - Requires implemention error in FileContainer to generate
logSys.error("Internal errror in FileContainer open method - please report as a bug to https://github.com/fail2ban/fail2ban/issues")
logSys.error("Internal error in FileContainer open method - please report as a bug to https://github.com/fail2ban/fail2ban/issues")
logSys.exception(e)
return False
# prevent completely read of big files first time (after start of service), initial seek to start time using half-interval search algorithm:
if container.getPos() == 0 and startTime is not None:
try:
# startTime = MyTime.time() - self.getFindTime()
self.seekToTime(container, startTime)
except Exception, e: # pragma: no cover
logSys.error("Error during seek to start time in \"%s\"", filename)
logSys.exception(e)
return False
# yoh: has_content is just a bool, so do not expect it to
# change -- loop is exited upon break, and is not entered at
@ -717,7 +722,7 @@ class FileFilter(Filter):
cntr = 0
unixTime = None
lasti = 0
movecntr = 3
movecntr = 1
while maxp > minp:
i = int(minp + (maxp - minp) / 2)
pos = container.seek(i)
@ -726,6 +731,7 @@ class FileFilter(Filter):
lncntr = 5;
dateTimeMatch = None
llen = 0
if lastpos == pos:
i = pos
while True:
line = container.readline()
@ -763,6 +769,7 @@ class FileFilter(Filter):
lastpos = container.seek(lastFew, False)
else:
lastpos = container.seek(lastpos, False)
container.setPos(lastpos)
if logSys.getEffectiveLevel() <= logging.DEBUG:
logSys.debug("Position %s from %s, found time %s (%s) within %s seeks", lastpos, fs, unixTime,
(datetime.datetime.fromtimestamp(unixTime).strftime("%Y-%m-%d %H:%M:%S") if unixTime is not None else ''), cntr)
@ -943,10 +950,6 @@ class DNSUtils:
logSys.warning("Unable to find a corresponding IP address for %s: %s"
% (dns, e))
return list()
except socket.error, e:
logSys.warning("Socket error raised trying to resolve hostname %s: %s"
% (dns, e))
return list()
@staticmethod
def searchIP(text):
@ -967,7 +970,7 @@ class DNSUtils:
try:
socket.inet_aton(s[0])
return True
except socket.error:
except socket.error: # pragma: no cover
return False
@staticmethod

View File

@ -27,7 +27,7 @@ import unittest
import getpass
import os
import sys
import time
import time, datetime
import tempfile
import uuid
@ -38,7 +38,7 @@ except ImportError:
from ..server.jail import Jail
from ..server.filterpoll import FilterPoll
from ..server.filter import Filter, FileFilter, DNSUtils
from ..server.filter import Filter, FileFilter, FileContainer, DNSUtils
from ..server.failmanager import FailManagerEmpty
from ..server.mytime import MyTime
from .utils import setUpMyTime, tearDownMyTime, mtimesleep, LogCaptureTestCase
@ -314,6 +314,60 @@ class LogFileFilterPoll(unittest.TestCase):
self.assertTrue(self.filter.isModified(LogFileFilterPoll.FILENAME))
self.assertFalse(self.filter.isModified(LogFileFilterPoll.FILENAME))
def testSeekToTime(self):
fname = tempfile.mktemp(prefix='tmp_fail2ban', suffix='.log')
tm = lambda time: datetime.datetime.fromtimestamp(time).strftime("%Y-%m-%d %H:%M:%S")
time = 1417512352
f = open(fname, 'w')
fc = FileContainer(fname, self.filter.getLogEncoding())
fc.open()
fc.setPos(0); self.filter.seekToTime(fc, time)
try:
f.flush()
# empty :
fc.setPos(0); self.filter.seekToTime(fc, time)
self.assertEqual(fc.getPos(), 0)
# one entry with exact time:
f.write("%s [sshd] error: PAM: failure len 1\n" % tm(time))
f.flush()
fc.setPos(0); self.filter.seekToTime(fc, time)
# one entry with smaller time:
f.seek(0)
f.write("%s [sshd] error: PAM: failure len 1\n" % tm(time - 10))
f.flush()
fc.setPos(0); self.filter.seekToTime(fc, time)
self.assertEqual(fc.getPos(), 0)
f.write("%s [sshd] error: PAM: failure len 3 2 1\n" % tm(time - 9))
f.flush()
fc.setPos(0); self.filter.seekToTime(fc, time)
self.assertEqual(fc.getPos(), 0)
# add exact time between:
f.write("%s [sshd] error: PAM: failure\n" % tm(time - 1))
f.flush()
fc.setPos(0); self.filter.seekToTime(fc, time)
self.assertEqual(fc.getPos(), 110)
# stil one exact line:
f.write("%s [sshd] error: PAM: Authentication failure\n" % tm(time))
f.write("%s [sshd] error: PAM: failure len 1\n" % tm(time))
f.flush()
fc.setPos(0); self.filter.seekToTime(fc, time)
self.assertEqual(fc.getPos(), 110)
# add something hereafter:
f.write("%s [sshd] error: PAM: failure len 3 2 1\n" % tm(time + 2))
f.write("%s [sshd] error: PAM: Authentication failure\n" % tm(time + 3))
f.flush()
fc.setPos(0); self.filter.seekToTime(fc, time)
self.assertEqual(fc.getPos(), 110)
# add something hereafter:
f.write("%s [sshd] error: PAM: failure\n" % tm(time + 9))
f.write("%s [sshd] error: PAM: failure len 3 2 1\n" % tm(time + 9))
f.flush()
fc.setPos(0); self.filter.seekToTime(fc, time)
self.assertEqual(fc.getPos(), 110)
finally:
fc.close()
_killfile(f, fname)
class LogFileMonitor(LogCaptureTestCase):
"""Few more tests for FilterPoll API