[tor-commits] [stem/master] Running tor instances for integ tests

atagar at torproject.org atagar at torproject.org
Sun Oct 16 08:22:09 UTC 2011


commit bdbf352ad7f56aec17ce0156eaf53c9a6ac1fe68
Author: Damian Johnson <atagar at 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 ""
 



More information about the tor-commits mailing list