commit bdbf352ad7f56aec17ce0156eaf53c9a6ac1fe68 Author: Damian Johnson atagar@torproject.org Date: Sun Oct 16 01:17:38 2011 -0700
Running tor instances for integ tests
First draft for the startup/shutdown of integration tests. This... - makes a test directory - generates a torrc - starts a tor instance, waiting until its bootstrap completes (timing out if it gets stuck) - runs tests (not done yet - those are next) - shuts down the tor instance
This'll certainly go through some refactoring to better modularize, but it's functional as-is. --- run_tests.py | 143 +++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 123 insertions(+), 20 deletions(-)
diff --git a/run_tests.py b/run_tests.py index 78f392d..9e4487c 100755 --- a/run_tests.py +++ b/run_tests.py @@ -4,13 +4,18 @@ Runs unit and integration tests. """
+import os import sys +import time import getopt +import signal +import tempfile import unittest +import subprocess import test.unit.message import test.unit.version
-from stem.util import enum, term +from stem.util import enum, system, term
OPT = "uit:h" OPT_EXPANDED = ["unit", "integ", "targets=", "help"] @@ -46,6 +51,57 @@ Runs tests for the stem library. %s """
+# Number of seconds before we time out our attempt to start a tor instance +TOR_INIT_TIMEOUT = 20 + +def init_tor_process(torrc_dst): + """ + Initializes and returns a tor process. This blocks until initialization + completes or we error out. + + Arguments: + torrc_dst (str) - path for a torrc configuration to use + + Returns: + subprocess.Popen instance for the instantiated tor process + + Raises: + OSError if we either fail to create the tor process or reached a timeout without success + """ + + start_time = time.time() + + # starts a tor subprocess, raising an OSError if it fails + tor_process = subprocess.Popen(["tor", "-f", torrc_dst], stdout = subprocess.PIPE, stderr = subprocess.PIPE) + + # time ourselves out if we reach TOR_INIT_TIMEOUT + def timeout_handler(signum, frame): + # terminates the uninitialized tor process and raise on timeout + tor_process.kill() + raise OSError("unable to start tor: reached a %i second timeout without success" % TOR_INIT_TIMEOUT) + + signal.signal(signal.SIGALRM, timeout_handler) + signal.alarm(TOR_INIT_TIMEOUT) + + print term.format("Starting tor...", term.Color.BLUE, term.Attr.BOLD) + + while True: + init_line = tor_process.stdout.readline().strip() + + # this will provide empty results if the process is terminated + if not init_line: + tor_process.kill() # ... but best make sure + raise OSError("tor process terminated") + + print term.format(" %s" % init_line, term.Color.BLUE) + + # return the process if we're done with bootstrapping + if init_line.endswith("Bootstrapped 100%: Done."): + print term.format(" done (%i seconds)" % (time.time() - start_time), term.Color.BLUE, term.Attr.BOLD) + print + + return tor_process + if __name__ == '__main__': run_unit_tests = False run_integ_tests = False @@ -97,35 +153,82 @@ if __name__ == '__main__':
for name, test_class in UNIT_TESTS: print "%s\n%s\n%s\n" % (DIVIDER, name, DIVIDER) - #print name suite = unittest.TestLoader().loadTestsFromTestCase(test_class) unittest.TextTestRunner(verbosity=2).run(suite) print
- #import test.unit - #suite = unittest.TestLoader().loadTestsFromTestCase(test.unit.version.TestVerionFunctions) - #suite = unittest.TestLoader().discover("test/unit/", "*.py") - #suite.addTests(unittest.loader.loadTestsFromTestCase(test.unit.message.TestMessageFunctions)) - - #suite = unittest.TestLoader() - #suite.loadTestsFromTestCase(test.unit.message.TestMessageFunctions) - #suite.loadTestsFromTestCase(test.unit.version.TestVerionFunctions) - #unittest.TextTestRunner(verbosity=2).run(suite) - print
if run_integ_tests: + # TODO: check if there's already a tor instance running + print "%s\n%s\n%s\n" % (DIVIDER, "INTEGRATION TESTS".center(70), DIVIDER)
- for target in integ_targets: - runner, description = TARGET_ATTR[target] + print term.format("Setting up a test instance...", term.Color.BLUE, term.Attr.BOLD) + + # makes a temporary directory for the runtime resources of our integ test + test_dir = tempfile.mktemp("-stem-integ") + + try: + os.makedirs(test_dir) + print term.format(" created test directory: %s" % test_dir, term.Color.BLUE, term.Attr.BOLD) + except OSError, exc: + print term.format("Unable to make testing directory: %s" % exc, term.Color.RED, term.Attr.BOLD) + sys.exit(1) + + # makes a basic torrc for the integration tests to run against + torrc_contents = """# basic integration testing configuration +DataDirectory %s +ControlPort 9051 +""" % test_dir + + # writes our testing torrc + torrc_dst = os.path.join(test_dir, "torrc") + try: + torrc_file = open(torrc_dst, "w") + torrc_file.write(torrc_contents) + torrc_file.close()
- print "Configuration: %s - %s" % (target, description) + print term.format(" wrote torrc: %s" % torrc_dst, term.Color.BLUE, term.Attr.BOLD)
- if runner: - pass # TODO: implement - else: - print " %s" % term.format("Unimplemented", term.Color.RED, term.Attr.BOLD) + for line in torrc_contents.split("\n"): + print term.format(" %s" % line.strip(), term.Color.BLUE) + except Exception, exc: + print term.format("Unable to write testing torrc: %s" % exc, term.Color.RED, term.Attr.BOLD) + sys.exit(1) + + # starts a tor instance + try: + tor_process = init_tor_process(torrc_dst) + except OSError, exc: + print term.format("Unable to start a tor instance: %s" % exc, term.Color.RED, term.Attr.BOLD) + sys.exit(1)
- print "" + print term.format("Running tests...", term.Color.BLUE, term.Attr.BOLD) + print + + # TODO: run tests + + print term.format("Shutting down tor...", term.Color.BLUE, term.Attr.BOLD) + tor_process.kill() + print term.format(" done", term.Color.BLUE, term.Attr.BOLD) + + + + + + # TODO: we might do target selection later but for now we should simply + # work with a single simple tor instance and see how it works out + # + #for target in integ_targets: + # runner, description = TARGET_ATTR[target] + # + # print "Configuration: %s - %s" % (target, description) + # + # if runner: + # pass # TODO: implement + # else: + # print " %s" % term.format("Unimplemented", term.Color.RED, term.Attr.BOLD) + # + # print ""
tor-commits@lists.torproject.org