diff --git a/fail2ban-testcases b/fail2ban-testcases index f1ae476d..f44e84d4 100755 --- a/fail2ban-testcases +++ b/fail2ban-testcases @@ -49,6 +49,7 @@ if json: from testcases import samplestestcase from testcases.utils import FormatterWithTraceBack +from testcases import actionstestcase from server.mytime import MyTime from optparse import OptionParser, Option @@ -153,6 +154,7 @@ else: # pragma: no cover tests.addTest(unittest.makeSuite(servertestcase.Transmitter)) tests.addTest(unittest.makeSuite(servertestcase.JailTests)) tests.addTest(unittest.makeSuite(actiontestcase.ExecuteAction)) +tests.addTest(unittest.makeSuite(actionstestcase.ExecuteActions)) # FailManager tests.addTest(unittest.makeSuite(failmanagertestcase.AddFailure)) # BanManager diff --git a/testcases/actionstestcase.py b/testcases/actionstestcase.py new file mode 100644 index 00000000..3bb01a6d --- /dev/null +++ b/testcases/actionstestcase.py @@ -0,0 +1,79 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: t -*- +# vi: set ft=python sts=4 ts=4 sw=4 noet : + +# This file is part of Fail2Ban. +# +# Fail2Ban is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# Fail2Ban is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Fail2Ban; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# Author: Daniel Black +# + +__author__ = "Daniel Black" +__copyright__ = "Copyright (c) 2013 Daniel Black" +__license__ = "GPL" + +import unittest, time +import sys, os, tempfile +from server.actions import Actions +from dummyjail import DummyJail + +class ExecuteActions(unittest.TestCase): + + def setUp(self): + """Call before every test case.""" + self.__jail = DummyJail() + self.__actions = Actions(self.__jail) + self.__tmpfile, self.__tmpfilename = tempfile.mkstemp() + + def tearDown(self): + os.remove(self.__tmpfilename) + + def defaultActions(self): + self.__actions.addAction('ip') + self.__ip = self.__actions.getAction('ip') + self.__ip.setActionStart('echo ip start 64 >> "%s"' % self.__tmpfilename ) + self.__ip.setActionBan('echo ip ban >> "%s"' % self.__tmpfilename ) + self.__ip.setActionUnban('echo ip unban >> "%s"' % self.__tmpfilename ) + self.__ip.setActionCheck('echo ip check >> "%s"' % self.__tmpfilename ) + self.__ip.setActionStop('echo ip stop >> "%s"' % self.__tmpfilename ) + + def testActionsManipulation(self): + self.__actions.addAction('test') + self.assertTrue(self.__actions.getAction('test')) + self.assertTrue(self.__actions.getLastAction()) + self.assertRaises(KeyError,self.__actions.getAction,*['nonexistant action']) + self.__actions.addAction('test1') + self.__actions.delAction('test') + self.__actions.delAction('test1') + self.assertRaises(KeyError, self.__actions.getAction, *['test']) + self.assertRaises(IndexError,self.__actions.getLastAction) + + self.__actions.setBanTime(127) + self.assertEqual(self.__actions.getBanTime(),127) + self.assertRaises(ValueError, self.__actions.removeBannedIP, '127.0.0.1') + + + def testActionsOutput(self): + self.defaultActions() + self.__actions.start() + with open(self.__tmpfilename) as f: + time.sleep(3) + self.assertEqual(f.read(),"ip start 64\n") + + self.__actions.stop() + self.__actions.join() + self.assertEqual(self.__actions.status(),[("Currently banned", 0 ), + ("Total banned", 0 ), ("IP list", [] )]) + diff --git a/testcases/dummyjail.py b/testcases/dummyjail.py new file mode 100644 index 00000000..bd11bd5b --- /dev/null +++ b/testcases/dummyjail.py @@ -0,0 +1,59 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: t -*- +# vi: set ft=python sts=4 ts=4 sw=4 noet : + +# This file is part of Fail2Ban. +# +# Fail2Ban is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# Fail2Ban is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Fail2Ban; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# Fail2Ban developers + +__copyright__ = "Copyright (c) 2012 Yaroslav Halchenko" +__license__ = "GPL" + +from threading import Lock +class DummyJail(object): + """A simple 'jail' to suck in all the tickets generated by Filter's + """ + def __init__(self): + self.lock = Lock() + self.queue = [] + + def __len__(self): + try: + self.lock.acquire() + return len(self.queue) + finally: + self.lock.release() + + def putFailTicket(self, ticket): + try: + self.lock.acquire() + self.queue.append(ticket) + finally: + self.lock.release() + + def getFailTicket(self): + try: + self.lock.acquire() + try: + return self.queue.pop() + except IndexError: + return False + finally: + self.lock.release() + + def getName(self): + return "DummyJail #%s with %d tickets" % (id(self), len(self)) +