From: Jelmer Vernooij Date: Sun, 11 Mar 2012 19:58:00 +0000 (+0100) Subject: selftest.py: Move some infrastructure for running commands to selftest.run, with... X-Git-Tag: samba-4.0.0alpha19~378 X-Git-Url: http://git.samba.org/samba.git/?a=commitdiff_plain;h=6f9c333f95956138fbd8245a4cf3f285ca601181;p=sharpe%2Fsamba-autobuild%2F.git selftest.py: Move some infrastructure for running commands to selftest.run, with tests. --- diff --git a/selftest/run.py b/selftest/run.py index 20ede655321..24fbc339e63 100644 --- a/selftest/run.py +++ b/selftest/run.py @@ -15,7 +15,14 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +"""Test command running.""" + +import datetime +import iso8601 import os +import subprocess +import subunit +import sys import tempfile import warnings @@ -77,3 +84,51 @@ def exported_envvars_str(vars, names): continue out += "%s=%s\n" % (n, vars[n]) return out + + +def now(): + """Return datetime instance for current time in UTC. + """ + return datetime.datetime.utcnow().replace(tzinfo=iso8601.iso8601.Utc()) + + +def run_testsuite_command(name, cmd, subunit_ops, env=None, outf=None): + """Run a testsuite command. + + :param name: Name of the testsuite + :param cmd: Command to run + :param subunit_ops: Subunit ops to use for reporting results + :param env: Environment the test is run in + :param outf: File-like object to write standard out to (defaults to sys.stdout) + :return: Exit code or None if the test failed to run completely + """ + if outf is None: + outf = sys.stdout + subunit_ops.start_testsuite(name) + subunit_ops.progress(None, subunit.PROGRESS_PUSH) + subunit_ops.time(now()) + try: + exitcode = subprocess.call(cmd, shell=True, stdout=outf) + except Exception, e: + subunit_ops.time(now()) + subunit_ops.progress(None, subunit.PROGRESS_POP) + subunit_ops.end_testsuite(name, "error", "Unable to run %r: %s" % (cmd, e)) + return None + + subunit_ops.time(now()) + subunit_ops.progress(None, subunit.PROGRESS_POP) + + if env is not None: + envlog = env.get_log() + if envlog != "": + outf.write("envlog: %s\n" % envlog) + + outf.write("command: %s\n" % cmd) + outf.write("expanded command: %s\n" % expand_environment_strings(cmd, os.environ)) + + if exitcode == 0: + subunit_ops.end_testsuite(name, "success") + else: + subunit_ops.end_testsuite(name, "failure", "Exit code was %d" % exitcode) + + return exitcode diff --git a/selftest/selftest.py b/selftest/selftest.py index 1b2044134c8..f35541a3e53 100755 --- a/selftest/selftest.py +++ b/selftest/selftest.py @@ -18,8 +18,6 @@ import atexit from cStringIO import StringIO -import datetime -import iso8601 import os import sys import signal @@ -39,10 +37,11 @@ from selftest import ( ) from selftest.client import write_clientconf from selftest.run import ( - expand_environment_strings, expand_command_list, expand_command_run, exported_envvars_str, + now, + run_testsuite_command, ) from selftest.target import ( EnvironmentManager, @@ -53,9 +52,6 @@ from selftest.target import ( includes = () excludes = () -def now(): - return datetime.datetime.utcnow().replace(tzinfo=iso8601.iso8601.Utc()) - def read_excludes(fn): excludes.extend(testlist.read_test_regexes(fn)) @@ -123,42 +119,20 @@ def cleanup_pcap(pcap_file, exit_code): os.unlink(pcap_file) -def run_testsuite(envname, name, cmd): +def run_testsuite(name, cmd, subunit_ops, env=None): """Run a single testsuite. - :param envname: Name of the environment to ru nin + :param env: Environment to run in :param name: Name of the testsuite :param cmd: Name of the (fully expanded) command to run :return: exitcode of the command """ pcap_file = setup_pcap(name) - subunit_ops.start_testsuite(name) - subunit_ops.progress(None, subunit.PROGRESS_PUSH) - subunit_ops.time(now()) - try: - exitcode = subprocess.call(cmd, shell=True) - except Exception, e: - subunit_ops.time(now()) - subunit_ops.progress(None, subunit.PROGRESS_POP) - subunit_ops.end_testsuite(name, "error", "Unable to run %r: %s" % (cmd, e)) + exitcode = run_testsuite_command(name, cmd, subunit_ops, env) + if exitcode is None: sys.exit(1) - subunit_ops.time(now()) - subunit_ops.progress(None, subunit.PROGRESS_POP) - - envlog = env_manager.getlog_env(envname) - if envlog != "": - sys.stdout.write("envlog: %s\n" % envlog) - - sys.stdout.write("command: %s\n" % cmd) - sys.stdout.write("expanded command: %s\n" % expand_environment_strings(cmd, os.environ)) - - if exitcode == 0: - subunit_ops.end_testsuite(name, "success") - else: - subunit_ops.end_testsuite(name, "failure", "Exit code was %d" % exitcode) - cleanup_pcap(pcap_file, exitcode) if not opts.socket_wrapper_keep_pcap and pcap_file is not None: @@ -169,6 +143,7 @@ def run_testsuite(envname, name, cmd): return exitcode + if opts.list and opts.testenv: sys.stderr.write("--list and --testenv are mutually exclusive\n") sys.exit(1) @@ -273,9 +248,10 @@ else: # must terminate in this time, and testenv will only stay alive this # long -server_maxtime = 7500 if os.environ.get("SMBD_MAXTIME", ""): server_maxtime = int(os.environ["SMBD_MAXTIME"]) +else: + server_maxtime = 7500 def has_socket_wrapper(bindir): @@ -466,7 +442,7 @@ def switch_env(name, prefix): elif name in os.environ: del os.environ[name] - return testenv_vars + return env # This 'global' file needs to be empty when we start dns_host_file_path = os.path.join(prefix_abs, "dns_host_file") @@ -476,7 +452,8 @@ if os.path.exists(dns_host_file_path): if opts.testenv: testenv_name = os.environ.get("SELFTEST_TESTENV", testenv_default) - testenv_vars = switch_env(testenv_name, prefix) + env = switch_env(testenv_name, prefix) + testenv_vars = env.get_vars() os.environ["PIDDIR"] = testenv_vars["PIDDIR"] os.environ["ENVNAME"] = testenv_name @@ -515,7 +492,7 @@ elif opts.list: else: for (name, envname, cmd, supports_loadfile, supports_idlist, subtests) in todo: try: - envvars = switch_env(envname, prefix) + env = switch_env(envname, prefix) except UnsupportedEnvironment: subunit_ops.start_testsuite(name) subunit_ops.end_testsuite(name, "skip", @@ -531,7 +508,7 @@ else: cmd, tmpf = expand_command_run(cmd, supports_loadfile, supports_idlist, subtests) - run_testsuite(envname, name, cmd) + run_testsuite(name, cmd, subunit_ops, env=env) if tmpf is not None: os.remove(tmpf) diff --git a/selftest/tests/test_run.py b/selftest/tests/test_run.py index 894ceaa7fcc..de5f4b121bc 100644 --- a/selftest/tests/test_run.py +++ b/selftest/tests/test_run.py @@ -19,13 +19,18 @@ """Tests for selftest.run.""" +import datetime import os +import subunit +import tempfile from selftest.run import ( expand_command_list, expand_environment_strings, expand_command_run, exported_envvars_str, + now, + run_testsuite_command, ) from selftest.tests import TestCase @@ -92,3 +97,91 @@ class ExportedEnvvarsStrTests(TestCase): def test_vars_unknown(self): self.assertEquals("foo=1\n", exported_envvars_str({"foo": "1", "bla": "2"}, ["foo", "bar"])) + + + +class NowTests(TestCase): + + def test_basic(self): + self.assertIsInstance(now(), datetime.datetime) + self.assertIsNot(now().tzinfo, None) + + +class MockSubunitOps(object): + + def __init__(self): + self.calls = [] + + def start_testsuite(self, name): + self.calls.append(("start-testsuite", name)) + + def progress(self, count, whence): + self.calls.append(("progress", count, whence)) + + def time(self, t): + self.calls.append(("time", )) + + def end_testsuite(self, name, result, details=None): + self.calls.append(("end-testsuite", name, result, details)) + + +class RunTestsuiteCommandTests(TestCase): + + def test_success_no_env(self): + outf = tempfile.TemporaryFile() + subunit_ops = MockSubunitOps() + exit_code = run_testsuite_command("thetestsuitename", "echo doing something", subunit_ops, outf=outf) + self.assertEquals([ + ("start-testsuite", "thetestsuitename"), + ("progress", None, subunit.PROGRESS_PUSH), + ("time", ), + ("time", ), + ("progress", None, subunit.PROGRESS_POP), + ("end-testsuite", "thetestsuitename", "success", None), + ], subunit_ops.calls) + self.assertEquals(0, exit_code) + outf.seek(0) + self.assertEquals("""\ +doing something +command: echo doing something +expanded command: echo doing something +""", outf.read()) + + def test_failure(self): + outf = tempfile.TemporaryFile() + subunit_ops = MockSubunitOps() + exit_code = run_testsuite_command("thetestsuitename", "exit 3", subunit_ops, outf=outf) + self.assertEquals([ + ("start-testsuite", "thetestsuitename"), + ("progress", None, subunit.PROGRESS_PUSH), + ("time", ), + ("time", ), + ("progress", None, subunit.PROGRESS_POP), + ("end-testsuite", "thetestsuitename", "failure", "Exit code was 3"), + ], subunit_ops.calls) + self.assertEquals(3, exit_code) + outf.seek(0) + self.assertEquals("""\ +command: exit 3 +expanded command: exit 3 +""", outf.read()) + + def test_error(self): + outf = tempfile.TemporaryFile() + subunit_ops = MockSubunitOps() + exit_code = run_testsuite_command("thetestsuitename", + "thisisacommandthatdoesnotexist 2>/dev/null", subunit_ops, outf=outf) + self.assertEquals([ + ("start-testsuite", "thetestsuitename"), + ("progress", None, subunit.PROGRESS_PUSH), + ("time", ), + ("time", ), + ("progress", None, subunit.PROGRESS_POP), + ("end-testsuite", "thetestsuitename", "failure", "Exit code was 127"), + ], subunit_ops.calls) + self.assertEquals(127, exit_code) + outf.seek(0) + self.assertEquals("""\ +command: thisisacommandthatdoesnotexist 2>/dev/null +expanded command: thisisacommandthatdoesnotexist 2>/dev/null +""", outf.read())