RF: group common tests in base class, specialize assesment of good/bad runs per client/server

pull/1483/head
Yaroslav Halchenko 2016-07-11 23:26:30 -04:00
parent 4df06f5352
commit 1417cc99ef
1 changed files with 116 additions and 154 deletions

View File

@ -287,29 +287,91 @@ class Fail2banClientServerBase(LogCaptureTestCase):
logSys.debug("No log file %s to examine details of error", log) logSys.debug("No log file %s to examine details of error", log)
raise raise
def assertExitsNormally(self, args):
raise NotImplementedError("To be defined in subclass")
def assertExitsAbnormally(self, args):
raise NotImplementedError("To be defined in subclass")
#
# Common tests
#
def _testStartForeground(self, tmp, startparams, phase):
# start and wait to end (foreground):
logSys.debug("start of test worker")
phase['start'] = True
self.assertExitsNormally(("-f",) + startparams + ("start",))
# end :
phase['end'] = True
logSys.debug("end of test worker")
@with_tmpdir
def testStartForeground(self, tmp):
# intended to be ran only in subclasses
th = None
try:
# started directly here, so prevent overwrite test cases logger with "INHERITED"
startparams = _start_params(tmp, logtarget="INHERITED")
# because foreground block execution - start it in thread:
phase = dict()
th = Thread(
name="_TestCaseWorker",
target=self._testStartForeground,
args=(tmp, startparams, phase)
)
th.daemon = True
th.start()
try:
# wait for start thread:
Utils.wait_for(lambda: phase.get('start', None) is not None, MAX_WAITTIME)
self.assertTrue(phase.get('start', None))
# wait for server (socket and ready):
self._wait_for_srv(tmp, True, startparams=startparams)
self.pruneLog()
# several commands to server:
self.assertExitsNormally(startparams + ("ping",))
self.assertExitsAbnormally(startparams + ("~~unknown~cmd~failed~~",))
self.assertExitsNormally(startparams + ("echo", "TEST-ECHO",))
finally:
self.pruneLog()
# stop:
self.assertExitsNormally(startparams + ("stop",))
# wait for end:
Utils.wait_for(lambda: phase.get('end', None) is not None, MAX_WAITTIME)
self.assertTrue(phase.get('end', None))
self.assertLogged("Shutdown successful", "Exiting Fail2ban")
finally:
_kill_srv(tmp)
if th:
th.join()
class Fail2banClientTest(Fail2banClientServerBase): class Fail2banClientTest(Fail2banClientServerBase):
def assertExitsNormally(self, args):
self.assertRaises(ExitException, _exec_client, ((CLIENT,) + args))
def assertExitsAbnormally(self, args):
self.assertRaises(FailExitException, _exec_client, ((CLIENT,) + args))
def testConsistency(self): def testConsistency(self):
self.assertTrue(isfile(pjoin(BIN, CLIENT))) self.assertTrue(isfile(pjoin(BIN, CLIENT)))
self.assertTrue(isfile(pjoin(BIN, SERVER))) self.assertTrue(isfile(pjoin(BIN, SERVER)))
def testClientUsage(self): def testClientUsage(self):
self.assertRaises(ExitException, _exec_client, self.assertExitsNormally(("-h",))
(CLIENT, "-h",))
self.assertLogged("Usage: " + CLIENT) self.assertLogged("Usage: " + CLIENT)
self.assertLogged("Report bugs to ") self.assertLogged("Report bugs to ")
self.pruneLog() self.pruneLog()
self.assertRaises(ExitException, _exec_client, self.assertExitsNormally(("-vq", "-V",))
(CLIENT, "-vq", "-V",))
self.assertLogged("Fail2Ban v" + fail2bancmdline.version) self.assertLogged("Fail2Ban v" + fail2bancmdline.version)
@with_tmpdir @with_tmpdir
def testClientDump(self, tmp): def testClientDump(self, tmp):
# use here the stock configuration (if possible) # use here the stock configuration (if possible)
startparams = _start_params(tmp, True) startparams = _start_params(tmp, True)
self.assertRaises(ExitException, _exec_client, self.assertExitsNormally(
((CLIENT,) + startparams + ("-vvd",))) (startparams + ("-vvd",)))
self.assertLogged("Loading files") self.assertLogged("Loading files")
self.assertLogged("logtarget") self.assertLogged("logtarget")
@ -319,34 +381,34 @@ class Fail2banClientTest(Fail2banClientServerBase):
# use once the stock configuration (to test starting also) # use once the stock configuration (to test starting also)
startparams = _start_params(tmp, True) startparams = _start_params(tmp, True)
# start: # start:
self.assertRaises(ExitException, _exec_client, self.assertExitsNormally(
(CLIENT, "-b") + startparams + ("start",)) ("-b",) + startparams + ("start",))
# wait for server (socket and ready): # wait for server (socket and ready):
self._wait_for_srv(tmp, True, startparams=startparams) self._wait_for_srv(tmp, True, startparams=startparams)
self.assertLogged("Server ready") self.assertLogged("Server ready")
self.assertLogged("Exit with code 0") self.assertLogged("Exit with code 0")
try: try:
self.assertRaises(ExitException, _exec_client, self.assertExitsNormally(
(CLIENT,) + startparams + ("echo", "TEST-ECHO",)) startparams + ("echo", "TEST-ECHO",))
self.assertRaises(FailExitException, _exec_client, self.assertExitsAbnormally(
(CLIENT,) + startparams + ("~~unknown~cmd~failed~~",)) startparams + ("~~unknown~cmd~failed~~",))
self.pruneLog() self.pruneLog()
# start again (should fail): # start again (should fail):
self.assertRaises(FailExitException, _exec_client, self.assertExitsAbnormally(
(CLIENT, "-b") + startparams + ("start",)) ("-b",) + startparams + ("start",))
self.assertLogged("Server already running") self.assertLogged("Server already running")
finally: finally:
self.pruneLog() self.pruneLog()
# stop: # stop:
self.assertRaises(ExitException, _exec_client, self.assertExitsNormally(
(CLIENT,) + startparams + ("stop",)) startparams + ("stop",))
self.assertLogged("Shutdown successful") self.assertLogged("Shutdown successful")
self.assertLogged("Exit with code 0") self.assertLogged("Exit with code 0")
self.pruneLog() self.pruneLog()
# stop again (should fail): # stop again (should fail):
self.assertRaises(FailExitException, _exec_client, self.assertExitsAbnormally(
(CLIENT,) + startparams + ("stop",)) startparams + ("stop",))
self.assertLogged("Failed to access socket path") self.assertLogged("Failed to access socket path")
self.assertLogged("Is fail2ban running?") self.assertLogged("Is fail2ban running?")
@ -367,8 +429,7 @@ class Fail2banClientTest(Fail2banClientServerBase):
self.pruneLog() self.pruneLog()
try: try:
# echo from client (inside): # echo from client (inside):
self.assertRaises(ExitException, _exec_client, self.assertExitsNormally(startparams + ("echo", "TEST-ECHO",))
(CLIENT,) + startparams + ("echo", "TEST-ECHO",))
self.assertLogged("TEST-ECHO") self.assertLogged("TEST-ECHO")
self.assertLogged("Exit with code 0") self.assertLogged("Exit with code 0")
self.pruneLog() self.pruneLog()
@ -378,8 +439,8 @@ class Fail2banClientTest(Fail2banClientServerBase):
"status", "status",
"exit" "exit"
] ]
self.assertRaises(ExitException, _exec_client, self.assertExitsNormally(
(CLIENT,) + startparams + ("-i",)) startparams + ("-i",))
self.assertLogged("INTERACT-ECHO") self.assertLogged("INTERACT-ECHO")
self.assertLogged("Status", "Number of jail:") self.assertLogged("Status", "Number of jail:")
self.assertLogged("Exit with code 0") self.assertLogged("Exit with code 0")
@ -390,8 +451,8 @@ class Fail2banClientTest(Fail2banClientServerBase):
"restart", "restart",
"exit" "exit"
] ]
self.assertRaises(ExitException, _exec_client, self.assertExitsNormally(
(CLIENT,) + startparams + ("-i",)) startparams + ("-i",))
self.assertLogged("Reading config files:") self.assertLogged("Reading config files:")
self.assertLogged("Shutdown successful") self.assertLogged("Shutdown successful")
self.assertLogged("Server ready") self.assertLogged("Server ready")
@ -402,74 +463,23 @@ class Fail2banClientTest(Fail2banClientServerBase):
"reload ~~unknown~jail~fail~~", "reload ~~unknown~jail~fail~~",
"exit" "exit"
] ]
self.assertRaises(ExitException, _exec_client, self.assertExitsNormally(
(CLIENT,) + startparams + ("-i",)) startparams + ("-i",))
self.assertLogged("Failed during configuration: No section: '~~unknown~jail~fail~~'") self.assertLogged("Failed during configuration: No section: '~~unknown~jail~fail~~'")
self.pruneLog() self.pruneLog()
# test reload missing jail (direct): # test reload missing jail (direct):
self.assertRaises(FailExitException, _exec_client, self.assertExitsAbnormally(
(CLIENT,) + startparams + ("reload", "~~unknown~jail~fail~~")) startparams + ("reload", "~~unknown~jail~fail~~"))
self.assertLogged("Failed during configuration: No section: '~~unknown~jail~fail~~'") self.assertLogged("Failed during configuration: No section: '~~unknown~jail~fail~~'")
self.assertLogged("Exit with code -1") self.assertLogged("Exit with code -1")
self.pruneLog() self.pruneLog()
finally: finally:
self.pruneLog() self.pruneLog()
# stop: # stop:
self.assertRaises(ExitException, _exec_client, self.assertExitsNormally(startparams + ("stop",))
(CLIENT,) + startparams + ("stop",))
self.assertLogged("Shutdown successful") self.assertLogged("Shutdown successful")
self.assertLogged("Exit with code 0") self.assertLogged("Exit with code 0")
def _testClientStartForeground(self, tmp, startparams, phase):
# start and wait to end (foreground):
logSys.debug("start of test worker")
phase['start'] = True
self.assertRaises(fail2bancmdline.ExitException, _exec_client,
(CLIENT, "-f") + startparams + ("start",))
# end :
phase['end'] = True
logSys.debug("end of test worker")
@with_tmpdir
def testClientStartForeground(self, tmp):
th = None
try:
# started directly here, so prevent overwrite test cases logger with "INHERITED"
startparams = _start_params(tmp, logtarget="INHERITED")
# because foreground block execution - start it in thread:
phase = dict()
th = Thread(name="_TestCaseWorker",
target=Fail2banClientTest._testClientStartForeground, args=(self, tmp, startparams, phase))
th.daemon = True
th.start()
try:
# wait for start thread:
Utils.wait_for(lambda: phase.get('start', None) is not None, MAX_WAITTIME)
self.assertTrue(phase.get('start', None))
# wait for server (socket and ready):
self._wait_for_srv(tmp, True, startparams=startparams)
self.pruneLog()
# several commands to server:
self.assertRaises(ExitException, _exec_client,
(CLIENT,) + startparams + ("ping",))
self.assertRaises(FailExitException, _exec_client,
(CLIENT,) + startparams + ("~~unknown~cmd~failed~~",))
self.assertRaises(ExitException, _exec_client,
(CLIENT,) + startparams + ("echo", "TEST-ECHO",))
finally:
self.pruneLog()
# stop:
self.assertRaises(ExitException, _exec_client,
(CLIENT,) + startparams + ("stop",))
# wait for end:
Utils.wait_for(lambda: phase.get('end', None) is not None, MAX_WAITTIME)
self.assertTrue(phase.get('end', None))
self.assertLogged("Shutdown successful", "Exiting Fail2ban")
finally:
_kill_srv(tmp)
if th:
th.join()
@with_tmpdir @with_tmpdir
@with_kill_srv @with_kill_srv
def testClientFailStart(self, tmp): def testClientFailStart(self, tmp):
@ -477,34 +487,34 @@ class Fail2banClientTest(Fail2banClientServerBase):
startparams = _start_params(tmp, logtarget="INHERITED") startparams = _start_params(tmp, logtarget="INHERITED")
## wrong config directory ## wrong config directory
self.assertRaises(FailExitException, _exec_client, self.assertExitsAbnormally(
(CLIENT, "--async", "-c", pjoin(tmp, "miss"), "start",)) ("--async", "-c", pjoin(tmp, "miss"), "start",))
self.assertLogged("Base configuration directory " + pjoin(tmp, "miss") + " does not exist") self.assertLogged("Base configuration directory " + pjoin(tmp, "miss") + " does not exist")
self.pruneLog() self.pruneLog()
## wrong socket ## wrong socket
self.assertRaises(FailExitException, _exec_client, self.assertExitsAbnormally(
(CLIENT, "--async", "-c", pjoin(tmp, "config"), "-s", pjoin(tmp, "miss/f2b.sock"), "start",)) ("--async", "-c", pjoin(tmp, "config"), "-s", pjoin(tmp, "miss/f2b.sock"), "start",))
self.assertLogged("There is no directory " + pjoin(tmp, "miss") + " to contain the socket file") self.assertLogged("There is no directory " + pjoin(tmp, "miss") + " to contain the socket file")
self.pruneLog() self.pruneLog()
## not running ## not running
self.assertRaises(FailExitException, _exec_client, self.assertExitsAbnormally(
(CLIENT, "-c", pjoin(tmp, "config"), "-s", pjoin(tmp, "f2b.sock"), "reload",)) ("-c", pjoin(tmp, "config"), "-s", pjoin(tmp, "f2b.sock"), "reload",))
self.assertLogged("Could not find server") self.assertLogged("Could not find server")
self.pruneLog() self.pruneLog()
## already exists: ## already exists:
open(pjoin(tmp, "f2b.sock"), 'a').close() open(pjoin(tmp, "f2b.sock"), 'a').close()
self.assertRaises(FailExitException, _exec_client, self.assertExitsAbnormally(
(CLIENT, "--async", "-c", pjoin(tmp, "config"), "-s", pjoin(tmp, "f2b.sock"), "start",)) ("--async", "-c", pjoin(tmp, "config"), "-s", pjoin(tmp, "f2b.sock"), "start",))
self.assertLogged("Fail2ban seems to be in unexpected state (not running but the socket exists)") self.assertLogged("Fail2ban seems to be in unexpected state (not running but the socket exists)")
self.pruneLog() self.pruneLog()
os.remove(pjoin(tmp, "f2b.sock")) os.remove(pjoin(tmp, "f2b.sock"))
## wrong option: ## wrong option:
self.assertRaises(FailExitException, _exec_client, self.assertExitsAbnormally(
(CLIENT, "-s",)) ("-s",))
self.assertLogged("Usage: ") self.assertLogged("Usage: ")
self.pruneLog() self.pruneLog()
@ -522,9 +532,14 @@ class Fail2banClientTest(Fail2banClientServerBase):
class Fail2banServerTest(Fail2banClientServerBase): class Fail2banServerTest(Fail2banClientServerBase):
def assertExitsNormally(self, args):
self.assertRaises(ExitException, _exec_server, ((SERVER,) + args))
def assertExitsAbnormally(self, args):
self.assertRaises(FailExitException, _exec_server, ((SERVER,) + args))
def testServerUsage(self): def testServerUsage(self):
self.assertRaises(ExitException, _exec_server, self.assertExitsNormally(("-h",))
(SERVER, "-h",))
self.assertLogged("Usage: " + SERVER) self.assertLogged("Usage: " + SERVER)
self.assertLogged("Report bugs to ") self.assertLogged("Report bugs to ")
@ -544,68 +559,15 @@ class Fail2banServerTest(Fail2banClientServerBase):
self.assertLogged("Server ready") self.assertLogged("Server ready")
self.pruneLog() self.pruneLog()
try: try:
self.assertRaises(ExitException, _exec_server, self.assertExitsNormally(startparams + ("echo", "TEST-ECHO",))
(SERVER,) + startparams + ("echo", "TEST-ECHO",)) self.assertExitsAbnormally(startparams + ("~~unknown~cmd~failed~~",))
self.assertRaises(FailExitException, _exec_server,
(SERVER,) + startparams + ("~~unknown~cmd~failed~~",))
finally: finally:
self.pruneLog() self.pruneLog()
# stop: # stop:
self.assertRaises(ExitException, _exec_server, self.assertExitsNormally(startparams + ("stop",))
(SERVER,) + startparams + ("stop",))
self.assertLogged("Shutdown successful") self.assertLogged("Shutdown successful")
self.assertLogged("Exit with code 0") self.assertLogged("Exit with code 0")
def _testServerStartForeground(self, tmp, startparams, phase):
# start and wait to end (foreground):
logSys.debug("-- start of test worker")
phase['start'] = True
self.assertRaises(fail2bancmdline.ExitException, _exec_server,
(SERVER, "-f") + startparams + ("start",))
# end :
phase['end'] = True
logSys.debug("-- end of test worker")
@with_tmpdir
def testServerStartForeground(self, tmp):
th = None
try:
# started directly here, so prevent overwrite test cases logger with "INHERITED"
startparams = _start_params(tmp, logtarget="INHERITED")
# because foreground block execution - start it in thread:
phase = dict()
th = Thread(name="_TestCaseWorker",
target=Fail2banServerTest._testServerStartForeground, args=(self, tmp, startparams, phase))
th.daemon = True
th.start()
try:
# wait for start thread:
Utils.wait_for(lambda: phase.get('start', None) is not None, MAX_WAITTIME)
self.assertTrue(phase.get('start', None))
# wait for server (socket and ready):
self._wait_for_srv(tmp, True, startparams=startparams)
self.pruneLog()
# several commands to server:
self.assertRaises(ExitException, _exec_server,
(SERVER,) + startparams + ("ping",))
self.assertRaises(FailExitException, _exec_server,
(SERVER,) + startparams + ("~~unknown~cmd~failed~~",))
self.assertRaises(ExitException, _exec_server,
(SERVER,) + startparams + ("echo", "TEST-ECHO",))
finally:
self.pruneLog()
# stop:
self.assertRaises(ExitException, _exec_server,
(SERVER,) + startparams + ("stop",))
# wait for end:
Utils.wait_for(lambda: phase.get('end', None) is not None, MAX_WAITTIME)
self.assertTrue(phase.get('end', None))
self.assertLogged("Shutdown successful", "Exiting Fail2ban")
finally:
_kill_srv(tmp)
if th:
th.join()
@with_tmpdir @with_tmpdir
@with_kill_srv @with_kill_srv
def testServerFailStart(self, tmp): def testServerFailStart(self, tmp):
@ -613,21 +575,21 @@ class Fail2banServerTest(Fail2banClientServerBase):
startparams = _start_params(tmp, logtarget="INHERITED") startparams = _start_params(tmp, logtarget="INHERITED")
## wrong config directory ## wrong config directory
self.assertRaises(FailExitException, _exec_server, self.assertExitsAbnormally(
(SERVER, "-c", pjoin(tmp, "miss"),)) ("-c", pjoin(tmp, "miss"),))
self.assertLogged("Base configuration directory " + pjoin(tmp, "miss") + " does not exist") self.assertLogged("Base configuration directory " + pjoin(tmp, "miss") + " does not exist")
self.pruneLog() self.pruneLog()
## wrong socket ## wrong socket
self.assertRaises(FailExitException, _exec_server, self.assertExitsAbnormally(
(SERVER, "-c", pjoin(tmp, "config"), "-x", "-s", pjoin(tmp, "miss/f2b.sock"),)) ("-c", pjoin(tmp, "config"), "-x", "-s", pjoin(tmp, "miss/f2b.sock"),))
self.assertLogged("There is no directory " + pjoin(tmp, "miss") + " to contain the socket file") self.assertLogged("There is no directory " + pjoin(tmp, "miss") + " to contain the socket file")
self.pruneLog() self.pruneLog()
## already exists: ## already exists:
open(pjoin(tmp, "f2b.sock"), 'a').close() open(pjoin(tmp, "f2b.sock"), 'a').close()
self.assertRaises(FailExitException, _exec_server, self.assertExitsAbnormally(
(SERVER, "-c", pjoin(tmp, "config"), "-s", pjoin(tmp, "f2b.sock"),)) ("-c", pjoin(tmp, "config"), "-s", pjoin(tmp, "f2b.sock"),))
self.assertLogged("Fail2ban seems to be in unexpected state (not running but the socket exists)") self.assertLogged("Fail2ban seems to be in unexpected state (not running but the socket exists)")
self.pruneLog() self.pruneLog()
os.remove(pjoin(tmp, "f2b.sock")) os.remove(pjoin(tmp, "f2b.sock"))