diff --git a/test/boothrunner.py b/test/boothrunner.py index 77ea73b..ac56df8 100755 --- a/test/boothrunner.py +++ b/test/boothrunner.py @@ -1,108 +1,108 @@ #!/usr/bin/python import os import subprocess import time import unittest class BoothRunner: default_config_file = '/etc/booth/booth.conf' default_lock_file = '/var/run/booth.pid' def __init__(self, boothd_path, mode, args): self.boothd_path = boothd_path self.args = [ mode ] self.final_args = args # will be appended to self.args self.mode = mode self.config_file = None self.lock_file = None def set_config_file_arg(self): self.args += [ '-c', self.config_file ] def set_config_file(self, config_file): self.config_file = config_file self.set_config_file_arg() def set_lock_file(self, lock_file): self.lock_file = lock_file self.args += [ '-l', self.lock_file ] def set_debug(self): self.args += [ '-D' ] def all_args(self): return [ self.boothd_path ] + self.args + self.final_args def show_output(self, stdout, stderr): if stdout: print "STDOUT:" print "------" print stdout, if stderr: - print "STDERR:" + print "STDERR: (N.B. crm_ticket failures indicate daemon started correctly)" print "------" print stderr, print "-" * 70 def subproc_completed_within(self, p, timeout): start = time.time() wait = 0.1 while True: if p.poll() is not None: return True elapsed = time.time() - start if elapsed + wait > timeout: wait = timeout - elapsed print "Waiting on %d for %.1fs ..." % (p.pid, wait) time.sleep(wait) elapsed = time.time() - start if elapsed >= timeout: return False wait *= 2 def lock_file_used(self): return self.lock_file or self.default_lock_file def config_file_used(self): return self.config_file or self.default_config_file def config_text_used(self): config_file = self.config_file_used() try: c = open(config_file) except: return None text = "".join(c.readlines()) c.close() text = text.replace('\t', '') text = text.replace('\n', '|\n') return text def show_args(self): print "\n" print "-" * 70 print "Running", ' '.join(self.all_args()) msg = "with config from %s" % self.config_file_used() config_text = self.config_text_used() if config_text is not None: msg += ": [%s]" % config_text print msg def run(self): p = subprocess.Popen(self.all_args(), stdout=subprocess.PIPE, stderr=subprocess.PIPE) if not p: raise RuntimeError, "failed to start subprocess" print "Started subprocess pid %d" % p.pid completed = self.subproc_completed_within(p, 2) if completed: (stdout, stderr) = p.communicate() self.show_output(stdout, stderr) return (p.pid, p.returncode, stdout, stderr) return (p.pid, None, None, None) diff --git a/test/boothtestenv.py b/test/boothtestenv.py index 2f3abc6..eec3ffa 100755 --- a/test/boothtestenv.py +++ b/test/boothtestenv.py @@ -1,72 +1,73 @@ #!/usr/bin/python import os import subprocess import time import tempfile import unittest from assertions import BoothAssertions from boothrunner import BoothRunner class BoothTestEnvironment(unittest.TestCase, BoothAssertions): test_src_path = os.path.abspath(os.path.dirname(__file__)) dist_path = os.path.join(test_src_path, '..' ) src_path = os.path.join(dist_path, 'src' ) boothd_path = os.path.join(src_path, 'boothd') conf_path = os.path.join(dist_path, 'conf' ) example_config_path = os.path.join(conf_path, 'booth.conf.example') def setUp(self): if not self._testMethodName.startswith('test_'): raise RuntimeError, "unexpected test method name: " + self._testMethodName self.test_name = self._testMethodName[5:] self.test_path = os.path.join(self.test_run_path, self.test_name) os.makedirs(self.test_path) self.ensure_boothd_not_running() def ensure_boothd_not_running(self): # Need to redirect STDERR in case we're not root, in which # case netstat's -p option causes a warning. However we only # want to kill boothd processes which we own; -p will list the # pid for those and only those, which is exactly what we want # here. subprocess.call("netstat -tpln 2>&1 | perl -lne 'm,LISTEN\s+(\d+)/boothd, and kill 15, $1'", shell=True) def get_tempfile(self, identity): tf = tempfile.NamedTemporaryFile( prefix='%s.%d.' % (identity, time.time()), dir=self.test_path, delete=False ) return tf.name def init_log(self): self.log_file = self.get_tempfile('log') os.putenv('HA_debugfile', self.log_file) # See cluster-glue/lib/clplumbing/cl_log.c def read_log(self): if not os.path.exists(self.log_file): return '' l = open(self.log_file) msgs = ''.join(l.readlines()) l.close() return msgs def check_return_code(self, pid, return_code, expected_exitcode): if return_code is None: print "pid %d still running" % pid if expected_exitcode is not None: self.fail("expected exit code %d, not long-running process" % expected_exitcode) else: print "pid %d exited with code %d" % (pid, return_code) msg = "should exit with code %s" % expected_exitcode msg += "\nlog follows (see %s)" % self.log_file + msg += "\nN.B. expect mlockall/setscheduler errors when running tests non-root" msg += "\n-----------\n%s" % self.read_log() self.assertEqual(return_code, expected_exitcode, msg) def _test_buffer_overflow(self, expected_error, **args): (pid, ret, stdout, stderr, runner) = \ self.run_booth(expected_exitcode=1, **args) self.assertRegexpMatches(stderr, expected_error)