[tor-commits] [stem/master] TestCase's skipTest method unavailable before python 2.7

atagar at torproject.org atagar at torproject.org
Tue Jun 19 16:08:46 UTC 2012


commit ed0db8f0defa6d94e62b20c7a2cc335f3801d91a
Author: Damian Johnson <atagar at torproject.org>
Date:   Mon Jun 18 09:52:51 2012 -0700

    TestCase's skipTest method unavailable before python 2.7
    
    Blarg! The unit testing's skipTest method was a new addition in python 2.7.
    This is especially pesky since skipTest alters the control flow of the tests
    (raising an exception so we can place it in setUp methods).
    
    Options are to either monkey patch support into our testing module (ick!) or
    add a fallback everywhere we use skipTest. This change adds a best-effort skip
    method to the runner, then leaves it to the caller to return out of the method
    (reporting success for skipped tests).
    
    Sucks, but best that we can do until we drop *both* python 2.5 and 2.6
    compatability, which probably won't happen until we finally move to the 3.x
    series.
---
 test/integ/connection/authentication.py       |   23 ++++++-
 test/integ/connection/connect.py              |    6 +-
 test/integ/control/base_controller.py         |   17 ++++-
 test/integ/control/controller.py              |   15 +++-
 test/integ/descriptor/extrainfo_descriptor.py |    5 +-
 test/integ/descriptor/server_descriptor.py    |    5 +-
 test/integ/process.py                         |    4 +-
 test/integ/response/protocolinfo.py           |    9 ++-
 test/integ/socket/control_message.py          |   19 ++++-
 test/integ/socket/control_socket.py           |   15 +++-
 test/integ/util/system.py                     |  100 +++++++++++++++++--------
 test/integ/version.py                         |    8 +-
 test/runner.py                                |   30 +++++++-
 test/unit/descriptor/server_descriptor.py     |    7 +-
 14 files changed, 199 insertions(+), 64 deletions(-)

diff --git a/test/integ/connection/authentication.py b/test/integ/connection/authentication.py
index 31407a3..8c5c06d 100644
--- a/test/integ/connection/authentication.py
+++ b/test/integ/connection/authentication.py
@@ -95,7 +95,6 @@ def _get_auth_failure_message(auth_type):
 
 class TestAuthenticate(unittest.TestCase):
   def setUp(self):
-    test.runner.require_control(self)
     self.cookie_auth_methods = [AuthMethod.COOKIE]
     
     tor_version = test.runner.get_runner().get_tor_version()
@@ -107,6 +106,8 @@ class TestAuthenticate(unittest.TestCase):
     Tests that the authenticate function can authenticate to our socket.
     """
     
+    if test.runner.require_control(self): return
+    
     runner = test.runner.get_runner()
     with runner.get_tor_socket(False) as control_socket:
       stem.connection.authenticate(control_socket, test.runner.CONTROL_PASSWORD, runner.get_chroot())
@@ -117,6 +118,8 @@ class TestAuthenticate(unittest.TestCase):
     Tests that the authenticate function can authenticate via a Controller.
     """
     
+    if test.runner.require_control(self): return
+    
     runner = test.runner.get_runner()
     with runner.get_tor_controller(False) as controller:
       stem.connection.authenticate(controller, test.runner.CONTROL_PASSWORD, runner.get_chroot())
@@ -127,6 +130,8 @@ class TestAuthenticate(unittest.TestCase):
     Tests the authenticate function with something like its pydoc example.
     """
     
+    if test.runner.require_control(self): return
+    
     runner = test.runner.get_runner()
     tor_options = runner.get_options()
     
@@ -162,6 +167,8 @@ class TestAuthenticate(unittest.TestCase):
     Tests the authenticate function's password argument.
     """
     
+    if test.runner.require_control(self): return
+    
     # this is a much better test if we're just using password auth, since
     # authenticate will work reguardless if there's something else to
     # authenticate with
@@ -198,6 +205,8 @@ class TestAuthenticate(unittest.TestCase):
     individually.
     """
     
+    if test.runner.require_control(self): return
+    
     runner = test.runner.get_runner()
     tor_options = runner.get_options()
     is_cookie_only = test.runner.Torrc.COOKIE in tor_options and not test.runner.Torrc.PASSWORD in tor_options
@@ -220,6 +229,8 @@ class TestAuthenticate(unittest.TestCase):
     Tests the authenticate_none function.
     """
     
+    if test.runner.require_control(self): return
+    
     auth_type = stem.connection.AuthMethod.NONE
     
     if _can_authenticate(auth_type):
@@ -232,6 +243,8 @@ class TestAuthenticate(unittest.TestCase):
     Tests the authenticate_password function.
     """
     
+    if test.runner.require_control(self): return
+    
     auth_type = stem.connection.AuthMethod.PASSWORD
     auth_value = test.runner.CONTROL_PASSWORD
     
@@ -259,6 +272,8 @@ class TestAuthenticate(unittest.TestCase):
     Tests the authenticate_cookie function.
     """
     
+    if test.runner.require_control(self): return
+    
     auth_value = test.runner.get_runner().get_auth_cookie_path()
     
     for auth_type in self.cookie_auth_methods:
@@ -281,6 +296,8 @@ class TestAuthenticate(unittest.TestCase):
     value.
     """
     
+    if test.runner.require_control(self): return
+    
     auth_value = test.runner.get_runner().get_test_dir("fake_cookie")
     
     # we need to create a 32 byte cookie file to load from
@@ -317,6 +334,8 @@ class TestAuthenticate(unittest.TestCase):
     shouldn't exist.
     """
     
+    if test.runner.require_control(self): return
+    
     for auth_type in self.cookie_auth_methods:
       auth_value = "/if/this/exists/then/they're/asking/for/a/failure"
       self.assertRaises(stem.connection.UnreadableCookieFile, self._check_auth, auth_type, auth_value, False)
@@ -328,6 +347,8 @@ class TestAuthenticate(unittest.TestCase):
     socket.
     """
     
+    if test.runner.require_control(self): return
+    
     auth_value = test.runner.get_runner().get_torrc_path(True)
     
     for auth_type in self.cookie_auth_methods:
diff --git a/test/integ/connection/connect.py b/test/integ/connection/connect.py
index 3af249b..b3ba210 100644
--- a/test/integ/connection/connect.py
+++ b/test/integ/connection/connect.py
@@ -11,8 +11,6 @@ import test.runner
 
 class TestConnect(unittest.TestCase):
   def setUp(self):
-    test.runner.require_control(self)
-    
     # prevents the function from printing to the real stdout
     self.original_stdout = sys.stdout
     sys.stdout = StringIO.StringIO()
@@ -25,6 +23,8 @@ class TestConnect(unittest.TestCase):
     Basic sanity checks for the connect_port function.
     """
     
+    if test.runner.require_control(self): return
+    
     runner = test.runner.get_runner()
     
     control_socket = stem.connection.connect_port(
@@ -44,6 +44,8 @@ class TestConnect(unittest.TestCase):
     Basic sanity checks for the connect_socket_file function.
     """
     
+    if test.runner.require_control(self): return
+    
     runner = test.runner.get_runner()
     
     control_socket = stem.connection.connect_socket_file(
diff --git a/test/integ/control/base_controller.py b/test/integ/control/base_controller.py
index ab5ded5..d74c160 100644
--- a/test/integ/control/base_controller.py
+++ b/test/integ/control/base_controller.py
@@ -34,15 +34,14 @@ class StateObserver:
     self.timestamp = timestamp
 
 class TestBaseController(unittest.TestCase):
-  def setUp(self):
-    test.runner.require_control(self)
-  
   def test_connect_repeatedly(self):
     """
     Connects and closes the socket repeatedly. This is a simple attempt to
     trigger concurrency issues.
     """
     
+    if test.runner.require_control(self): return
+    
     with test.runner.get_runner().get_tor_socket() as control_socket:
       controller = stem.control.BaseController(control_socket)
       
@@ -55,6 +54,8 @@ class TestBaseController(unittest.TestCase):
     Tests a basic query with the msg() method.
     """
     
+    if test.runner.require_control(self): return
+    
     with test.runner.get_runner().get_tor_socket() as control_socket:
       controller = stem.control.BaseController(control_socket)
       test.runner.exercise_controller(self, controller)
@@ -64,6 +65,8 @@ class TestBaseController(unittest.TestCase):
     Tests the msg() method against an invalid controller command.
     """
     
+    if test.runner.require_control(self): return
+    
     with test.runner.get_runner().get_tor_socket() as control_socket:
       controller = stem.control.BaseController(control_socket)
       response = controller.msg("invalid")
@@ -74,6 +77,8 @@ class TestBaseController(unittest.TestCase):
     Tests the msg() method against a non-existant GETINFO option.
     """
     
+    if test.runner.require_control(self): return
+    
     with test.runner.get_runner().get_tor_socket() as control_socket:
       controller = stem.control.BaseController(control_socket)
       response = controller.msg("GETINFO blarg")
@@ -85,6 +90,8 @@ class TestBaseController(unittest.TestCase):
     is a simple attempt to trigger concurrency issues.
     """
     
+    if test.runner.require_control(self): return
+    
     with test.runner.get_runner().get_tor_socket() as control_socket:
       controller = stem.control.BaseController(control_socket)
       
@@ -119,6 +126,8 @@ class TestBaseController(unittest.TestCase):
     listeners will still receive all of the enqueued events.
     """
     
+    if test.runner.require_control(self): return
+    
     class ControlledListener(stem.control.BaseController):
       """
       Controller that blocks event handling until told to do so.
@@ -173,6 +182,8 @@ class TestBaseController(unittest.TestCase):
     remove_status_listener() methods.
     """
     
+    if test.runner.require_control(self): return
+    
     state_observer = StateObserver()
     
     with test.runner.get_runner().get_tor_socket(False) as control_socket:
diff --git a/test/integ/control/controller.py b/test/integ/control/controller.py
index 55a86ec..5c10b3d 100644
--- a/test/integ/control/controller.py
+++ b/test/integ/control/controller.py
@@ -13,14 +13,13 @@ import stem.response.protocolinfo
 import test.runner
 
 class TestController(unittest.TestCase):
-  def setUp(self):
-    test.runner.require_control(self)
-  
   def test_from_port(self):
     """
     Basic sanity check for the from_port constructor.
     """
     
+    if test.runner.require_control(self): return
+    
     if test.runner.Torrc.PORT in test.runner.get_runner().get_options():
       with stem.control.Controller.from_port(control_port = test.runner.CONTROL_PORT) as controller:
         self.assertTrue(isinstance(controller, stem.control.Controller))
@@ -32,6 +31,8 @@ class TestController(unittest.TestCase):
     Basic sanity check for the from_socket_file constructor.
     """
     
+    if test.runner.require_control(self): return
+    
     if test.runner.Torrc.SOCKET in test.runner.get_runner().get_options():
       with stem.control.Controller.from_socket_file(socket_path = test.runner.CONTROL_SOCKET_PATH) as controller:
         self.assertTrue(isinstance(controller, stem.control.Controller))
@@ -43,6 +44,8 @@ class TestController(unittest.TestCase):
     Exercises GETINFO with valid and invalid queries.
     """
     
+    if test.runner.require_control(self): return
+    
     runner = test.runner.get_runner()
     
     with runner.get_tor_controller() as controller:
@@ -80,6 +83,8 @@ class TestController(unittest.TestCase):
     Test that the convenient method get_version() works.
     """
     
+    if test.runner.require_control(self): return
+    
     runner = test.runner.get_runner()
     with runner.get_tor_controller() as controller:
       version = controller.get_version()
@@ -91,6 +96,8 @@ class TestController(unittest.TestCase):
     Test that the convenient method authenticate() works.
     """
     
+    if test.runner.require_control(self): return
+    
     runner = test.runner.get_runner()
     with runner.get_tor_controller(False) as controller:
       controller.authenticate(test.runner.CONTROL_PASSWORD)
@@ -101,6 +108,8 @@ class TestController(unittest.TestCase):
     Test that the convenient method protocolinfo() works.
     """
     
+    if test.runner.require_control(self): return
+    
     runner = test.runner.get_runner()
     
     with runner.get_tor_controller(False) as controller:
diff --git a/test/integ/descriptor/extrainfo_descriptor.py b/test/integ/descriptor/extrainfo_descriptor.py
index 45d1a2b..d960055 100644
--- a/test/integ/descriptor/extrainfo_descriptor.py
+++ b/test/integ/descriptor/extrainfo_descriptor.py
@@ -144,12 +144,13 @@ k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw
     """
     
     # lengthy test and uneffected by targets, so only run once
-    test.runner.only_run_once(self, "test_cached_descriptor")
+    if test.runner.only_run_once(self, "test_cached_descriptor"): return
     
     descriptor_path = test.runner.get_runner().get_test_dir("cached-extrainfo")
     
     if not os.path.exists(descriptor_path):
-      self.skipTest("(no cached descriptors)")
+      test.runner.skip(self, "(no cached descriptors)")
+      return
     
     with open(descriptor_path) as descriptor_file:
       for desc in stem.descriptor.extrainfo_descriptor.parse_file(descriptor_file):
diff --git a/test/integ/descriptor/server_descriptor.py b/test/integ/descriptor/server_descriptor.py
index 0af3cdf..7a3e2e6 100644
--- a/test/integ/descriptor/server_descriptor.py
+++ b/test/integ/descriptor/server_descriptor.py
@@ -146,12 +146,13 @@ Qlx9HNCqCY877ztFRC624ja2ql6A2hBcuoYMbkHjcQ4=
     """
     
     # lengthy test and uneffected by targets, so only run once
-    test.runner.only_run_once(self, "test_cached_descriptor")
+    if test.runner.only_run_once(self, "test_cached_descriptor"): return
     
     descriptor_path = test.runner.get_runner().get_test_dir("cached-descriptors")
     
     if not os.path.exists(descriptor_path):
-      self.skipTest("(no cached descriptors)")
+      test.runner.skip(self, "(no cached descriptors)")
+      return
     
     with open(descriptor_path) as descriptor_file:
       for desc in stem.descriptor.server_descriptor.parse_file(descriptor_file):
diff --git a/test/integ/process.py b/test/integ/process.py
index 61440fd..e3dd277 100644
--- a/test/integ/process.py
+++ b/test/integ/process.py
@@ -15,7 +15,7 @@ class TestProcess(unittest.TestCase):
     Exercises launch_tor_with_config.
     """
     
-    test.runner.only_run_once(self, "test_launch_tor_with_config")
+    if test.runner.only_run_once(self, "test_launch_tor_with_config"): return
     
     # Launch tor without a torrc, but with a control port. Confirms that this
     # works by checking that we're still able to access the new instance.
@@ -44,7 +44,7 @@ class TestProcess(unittest.TestCase):
     Runs launch_tor where it times out before completing.
     """
     
-    test.runner.only_run_once(self, "test_launch_tor_with_timeout")
+    if test.runner.only_run_once(self, "test_launch_tor_with_timeout"): return
     
     start_time = time.time()
     self.assertRaises(OSError, stem.process.launch_tor_with_config, {'SocksPort': '2777'}, "tor", 100, None, 2)
diff --git a/test/integ/response/protocolinfo.py b/test/integ/response/protocolinfo.py
index a80f406..4f13e7b 100644
--- a/test/integ/response/protocolinfo.py
+++ b/test/integ/response/protocolinfo.py
@@ -17,7 +17,6 @@ from test.integ.util.system import filter_system_call
 
 class TestProtocolInfo(unittest.TestCase):
   def setUp(self):
-    test.runner.require_control(self)
     mocking.mock(stem.util.proc.is_available, mocking.return_false())
     mocking.mock(stem.util.system.is_available, mocking.return_true())
   
@@ -30,6 +29,8 @@ class TestProtocolInfo(unittest.TestCase):
     connection.
     """
     
+    if test.runner.require_control(self): return
+    
     control_socket = test.runner.get_runner().get_tor_socket(False)
     control_socket.send("PROTOCOLINFO 1")
     protocolinfo_response = control_socket.recv()
@@ -56,6 +57,8 @@ class TestProtocolInfo(unittest.TestCase):
     with the 'RELATIVE' target.
     """
     
+    if test.runner.require_control(self): return
+    
     if test.runner.Torrc.PORT in test.runner.get_runner().get_options():
       cwd_by_port_lookup_prefixes = (
         stem.util.system.GET_PID_BY_PORT_NETSTAT,
@@ -89,6 +92,8 @@ class TestProtocolInfo(unittest.TestCase):
     re-establish it.
     """
     
+    if test.runner.require_control(self): return
+    
     with test.runner.get_runner().get_tor_socket(False) as control_socket:
       for i in range(5):
         protocolinfo_response = stem.connection.get_protocolinfo(control_socket)
@@ -100,6 +105,8 @@ class TestProtocolInfo(unittest.TestCase):
     already disconnected it.
     """
     
+    if test.runner.require_control(self): return
+    
     with test.runner.get_runner().get_tor_socket(False) as control_socket:
       # makes a couple protocolinfo queries outside of get_protocolinfo first
       control_socket.send("PROTOCOLINFO 1")
diff --git a/test/integ/socket/control_message.py b/test/integ/socket/control_message.py
index 1578917..cb2fe52 100644
--- a/test/integ/socket/control_message.py
+++ b/test/integ/socket/control_message.py
@@ -12,14 +12,13 @@ import stem.version
 import test.runner
 
 class TestControlMessage(unittest.TestCase):
-  def setUp(self):
-    test.runner.require_control(self)
-  
   def test_unestablished_socket(self):
     """
     Checks message parsing when we have a valid but unauthenticated socket.
     """
     
+    if test.runner.require_control(self): return
+    
     # If an unauthenticated connection gets a message besides AUTHENTICATE or
     # PROTOCOLINFO then tor will give an 'Authentication required.' message and
     # hang up.
@@ -60,6 +59,8 @@ class TestControlMessage(unittest.TestCase):
     Parses the response for a command which doesn't exist.
     """
     
+    if test.runner.require_control(self): return
+    
     with test.runner.get_runner().get_tor_socket() as control_socket:
       control_socket.send("blarg")
       unrecognized_command_response = control_socket.recv()
@@ -73,6 +74,8 @@ class TestControlMessage(unittest.TestCase):
     Parses the response for a GETINFO query which doesn't exist.
     """
     
+    if test.runner.require_control(self): return
+    
     with test.runner.get_runner().get_tor_socket() as control_socket:
       control_socket.send("GETINFO blarg")
       unrecognized_key_response = control_socket.recv()
@@ -86,6 +89,8 @@ class TestControlMessage(unittest.TestCase):
     Parses the 'GETINFO config-file' response.
     """
     
+    if test.runner.require_control(self): return
+    
     runner = test.runner.get_runner()
     torrc_dst = runner.get_torrc_path()
     
@@ -102,7 +107,11 @@ class TestControlMessage(unittest.TestCase):
     Parses the 'GETINFO config-text' response.
     """
     
-    test.runner.require_version(self, stem.version.Requirement.GETINFO_CONFIG_TEXT)
+    if test.runner.require_control(self):
+      return
+    elif test.runner.require_version(self, stem.version.Requirement.GETINFO_CONFIG_TEXT):
+      return
+    
     runner = test.runner.get_runner()
     
     # We can't be certain of the order, and there may be extra config-text
@@ -143,6 +152,8 @@ class TestControlMessage(unittest.TestCase):
     Issues 'SETEVENTS BW' and parses a couple events.
     """
     
+    if test.runner.require_control(self): return
+    
     with test.runner.get_runner().get_tor_socket() as control_socket:
       control_socket.send("SETEVENTS BW")
       setevents_response = control_socket.recv()
diff --git a/test/integ/socket/control_socket.py b/test/integ/socket/control_socket.py
index 1f06027..2e81599 100644
--- a/test/integ/socket/control_socket.py
+++ b/test/integ/socket/control_socket.py
@@ -18,14 +18,13 @@ import stem.socket
 import test.runner
 
 class TestControlSocket(unittest.TestCase):
-  def setUp(self):
-    test.runner.require_control(self)
-  
   def test_send_buffered(self):
     """
     Sends multiple requests before receiving back any of the replies.
     """
     
+    if test.runner.require_control(self): return
+    
     runner = test.runner.get_runner()
     tor_version = runner.get_tor_version()
     
@@ -43,6 +42,8 @@ class TestControlSocket(unittest.TestCase):
     Sends a message after we've closed the connection.
     """
     
+    if test.runner.require_control(self): return
+    
     with test.runner.get_runner().get_tor_socket() as control_socket:
       self.assertTrue(control_socket.is_alive())
       control_socket.close()
@@ -60,6 +61,8 @@ class TestControlSocket(unittest.TestCase):
     call. With a file socket, however, we'll also fail when calling send().
     """
     
+    if test.runner.require_control(self): return
+    
     with test.runner.get_runner().get_tor_socket() as control_socket:
       control_socket.send("QUIT")
       self.assertEquals("closing connection", str(control_socket.recv()))
@@ -80,6 +83,8 @@ class TestControlSocket(unittest.TestCase):
     Receives a message after we've closed the connection.
     """
     
+    if test.runner.require_control(self): return
+    
     with test.runner.get_runner().get_tor_socket() as control_socket:
       self.assertTrue(control_socket.is_alive())
       control_socket.close()
@@ -93,6 +98,8 @@ class TestControlSocket(unittest.TestCase):
     end.
     """
     
+    if test.runner.require_control(self): return
+    
     with test.runner.get_runner().get_tor_socket() as control_socket:
       control_socket.send("QUIT")
       self.assertEquals("closing connection", str(control_socket.recv()))
@@ -110,6 +117,8 @@ class TestControlSocket(unittest.TestCase):
     Checks that we can reconnect, use, and disconnect a socket repeatedly.
     """
     
+    if test.runner.require_control(self): return
+    
     with test.runner.get_runner().get_tor_socket(False) as control_socket:
       for i in range(10):
         # this will raise if the PROTOCOLINFO query fails
diff --git a/test/integ/util/system.py b/test/integ/util/system.py
index 607d9f7..60703e9 100644
--- a/test/integ/util/system.py
+++ b/test/integ/util/system.py
@@ -79,7 +79,8 @@ class TestSystem(unittest.TestCase):
     """
     
     if self.is_extra_tor_running:
-      self.skipTest("(multiple tor instances)")
+      test.runner.skip(self, "(multiple tor instances)")
+      return
     
     tor_pid = test.runner.get_runner().get_pid()
     self.assertEquals(tor_pid, stem.util.system.get_pid_by_name("tor"))
@@ -91,9 +92,11 @@ class TestSystem(unittest.TestCase):
     """
     
     if self.is_extra_tor_running:
-      self.skipTest("(multiple tor instances)")
+      test.runner.skip(self, "(multiple tor instances)")
+      return
     elif not stem.util.system.is_available("pgrep"):
-      self.skipTest("(pgrep unavailable)")
+      test.runner.skip(self, "(pgrep unavailable)")
+      return
     
     pgrep_prefix = stem.util.system.GET_PID_BY_NAME_PGREP % ""
     mocking.mock(stem.util.system.call, filter_system_call([pgrep_prefix]))
@@ -107,9 +110,11 @@ class TestSystem(unittest.TestCase):
     """
     
     if self.is_extra_tor_running:
-      self.skipTest("(multiple tor instances)")
+      test.runner.skip(self, "(multiple tor instances)")
+      return
     elif not stem.util.system.is_available("pidof"):
-      self.skipTest("(pidof unavailable)")
+      test.runner.skip(self, "(pidof unavailable)")
+      return
     
     pidof_prefix = stem.util.system.GET_PID_BY_NAME_PIDOF % ""
     mocking.mock(stem.util.system.call, filter_system_call([pidof_prefix]))
@@ -123,11 +128,14 @@ class TestSystem(unittest.TestCase):
     """
     
     if self.is_extra_tor_running:
-      self.skipTest("(multiple tor instances)")
+      test.runner.skip(self, "(multiple tor instances)")
+      return
     elif not stem.util.system.is_available("ps"):
-      self.skipTest("(ps unavailable)")
+      test.runner.skip(self, "(ps unavailable)")
+      return
     elif stem.util.system.is_bsd():
-      self.skipTest("(linux only)")
+      test.runner.skip(self, "(linux only)")
+      return
     
     ps_prefix = stem.util.system.GET_PID_BY_NAME_PS_LINUX % ""
     mocking.mock(stem.util.system.call, filter_system_call([ps_prefix]))
@@ -141,11 +149,14 @@ class TestSystem(unittest.TestCase):
     """
     
     if self.is_extra_tor_running:
-      self.skipTest("(multiple tor instances)")
+      test.runner.skip(self, "(multiple tor instances)")
+      return
     elif not stem.util.system.is_available("ps"):
-      self.skipTest("(ps unavailable)")
+      test.runner.skip(self, "(ps unavailable)")
+      return
     elif not stem.util.system.is_bsd():
-      self.skipTest("(bsd only)")
+      test.runner.skip(self, "(bsd only)")
+      return
     
     ps_prefix = stem.util.system.GET_PID_BY_NAME_PS_BSD
     mocking.mock(stem.util.system.call, filter_system_call([ps_prefix]))
@@ -160,11 +171,14 @@ class TestSystem(unittest.TestCase):
     
     runner = test.runner.get_runner()
     if self.is_extra_tor_running:
-      self.skipTest("(multiple tor instances)")
+      test.runner.skip(self, "(multiple tor instances)")
+      return
     elif not stem.util.system.is_available("lsof"):
-      self.skipTest("(lsof unavailable)")
+      test.runner.skip(self, "(lsof unavailable)")
+      return
     elif not runner.is_ptraceable():
-      self.skipTest("(DisableDebuggerAttachment is set)")
+      test.runner.skip(self, "(DisableDebuggerAttachment is set)")
+      return
     
     lsof_prefix = stem.util.system.GET_PID_BY_NAME_LSOF % ""
     mocking.mock(stem.util.system.call, filter_system_call([lsof_prefix]))
@@ -179,9 +193,11 @@ class TestSystem(unittest.TestCase):
     
     runner = test.runner.get_runner()
     if not _has_port():
-      self.skipTest("(test instance has no port)")
+      test.runner.skip(self, "(test instance has no port)")
+      return
     elif not runner.is_ptraceable():
-      self.skipTest("(DisableDebuggerAttachment is set)")
+      test.runner.skip(self, "(DisableDebuggerAttachment is set)")
+      return
     
     tor_pid, tor_port = runner.get_pid(), test.runner.CONTROL_PORT
     self.assertEquals(tor_pid, stem.util.system.get_pid_by_port(tor_port))
@@ -194,13 +210,17 @@ class TestSystem(unittest.TestCase):
     
     runner = test.runner.get_runner()
     if not _has_port():
-      self.skipTest("(test instance has no port)")
+      test.runner.skip(self, "(test instance has no port)")
+      return
     elif not stem.util.system.is_available("netstat"):
-      self.skipTest("(netstat unavailable)")
+      test.runner.skip(self, "(netstat unavailable)")
+      return
     elif stem.util.system.is_bsd():
-      self.skipTest("(linux only)")
+      test.runner.skip(self, "(linux only)")
+      return
     elif not runner.is_ptraceable():
-      self.skipTest("(DisableDebuggerAttachment is set)")
+      test.runner.skip(self, "(DisableDebuggerAttachment is set)")
+      return
     
     netstat_prefix = stem.util.system.GET_PID_BY_PORT_NETSTAT
     mocking.mock(stem.util.system.call, filter_system_call([netstat_prefix]))
@@ -215,13 +235,17 @@ class TestSystem(unittest.TestCase):
     
     runner = test.runner.get_runner()
     if not _has_port():
-      self.skipTest("(test instance has no port)")
+      test.runner.skip(self, "(test instance has no port)")
+      return
     elif not stem.util.system.is_available("sockstat"):
-      self.skipTest("(sockstat unavailable)")
+      test.runner.skip(self, "(sockstat unavailable)")
+      return
     elif not stem.util.system.is_bsd():
-      self.skipTest("(bsd only)")
+      test.runner.skip(self, "(bsd only)")
+      return
     elif not runner.is_ptraceable():
-      self.skipTest("(DisableDebuggerAttachment is set)")
+      test.runner.skip(self, "(DisableDebuggerAttachment is set)")
+      return
     
     sockstat_prefix = stem.util.system.GET_PID_BY_PORT_SOCKSTAT % ""
     mocking.mock(stem.util.system.call, filter_system_call([sockstat_prefix]))
@@ -236,11 +260,14 @@ class TestSystem(unittest.TestCase):
     
     runner = test.runner.get_runner()
     if not _has_port():
-      self.skipTest("(test instance has no port)")
+      test.runner.skip(self, "(test instance has no port)")
+      return
     elif not stem.util.system.is_available("lsof"):
-      self.skipTest("(lsof unavailable)")
+      test.runner.skip(self, "(lsof unavailable)")
+      return
     elif not runner.is_ptraceable():
-      self.skipTest("(DisableDebuggerAttachment is set)")
+      test.runner.skip(self, "(DisableDebuggerAttachment is set)")
+      return
     
     lsof_prefix = stem.util.system.GET_PID_BY_PORT_LSOF
     mocking.mock(stem.util.system.call, filter_system_call([lsof_prefix]))
@@ -254,7 +281,9 @@ class TestSystem(unittest.TestCase):
     """
     
     # on macs this test is unreliable because Quicklook sometimes claims '/tmp'
-    if os.uname()[0] == "Darwin": self.skipTest("(unreliable due to Quicklook)")
+    if os.uname()[0] == "Darwin":
+      test.runner.skip(self, "(unreliable due to Quicklook)")
+      return
     
     # we're not running with a control socket so this just exercises the
     # failure case
@@ -270,7 +299,8 @@ class TestSystem(unittest.TestCase):
     runner = test.runner.get_runner()
     
     if not runner.is_ptraceable():
-      self.skipTest("(DisableDebuggerAttachment is set)")
+      test.runner.skip(self, "(DisableDebuggerAttachment is set)")
+      return
     
     runner_pid, tor_cwd = runner.get_pid(), runner.get_tor_cwd()
     self.assertEquals(tor_cwd, stem.util.system.get_cwd(runner_pid))
@@ -283,9 +313,11 @@ class TestSystem(unittest.TestCase):
     
     runner = test.runner.get_runner()
     if not stem.util.system.is_available("pwdx"):
-      self.skipTest("(pwdx unavailable)")
+      test.runner.skip(self, "(pwdx unavailable)")
+      return
     elif not runner.is_ptraceable():
-      self.skipTest("(DisableDebuggerAttachment is set)")
+      test.runner.skip(self, "(DisableDebuggerAttachment is set)")
+      return
     
     # filter the call function to only allow this command
     pwdx_prefix = stem.util.system.GET_CWD_PWDX % ""
@@ -301,9 +333,11 @@ class TestSystem(unittest.TestCase):
     
     runner = test.runner.get_runner()
     if not stem.util.system.is_available("lsof"):
-      self.skipTest("(lsof unavailable)")
+      test.runner.skip(self, "(lsof unavailable)")
+      return
     elif not runner.is_ptraceable():
-      self.skipTest("(DisableDebuggerAttachment is set)")
+      test.runner.skip(self, "(DisableDebuggerAttachment is set)")
+      return
     
     # filter the call function to only allow this command
     lsof_prefix = "lsof -a -p "
diff --git a/test/integ/version.py b/test/integ/version.py
index 906edbc..34edec9 100644
--- a/test/integ/version.py
+++ b/test/integ/version.py
@@ -5,6 +5,7 @@ running with.
 
 import unittest
 
+import stem.prereq
 import test.runner
 import stem.version
 
@@ -15,7 +16,8 @@ class TestVersion(unittest.TestCase):
     """
     
     if not stem.util.system.is_available("tor"):
-      self.skipTest("(tor isn't in our path)")
+      test.runner.skip(self, "(tor isn't in our path)")
+      return
     
     # Since tor is in our path we should expect to be able to get the version
     # that way, though this might not belong to our test instance (if we're
@@ -35,7 +37,7 @@ class TestVersion(unittest.TestCase):
     test instance provides.
     """
     
-    test.runner.require_control(self)
+    if test.runner.require_control(self): return
     
     runner = test.runner.get_runner()
     system_tor_version = stem.version.get_system_tor_version(runner.get_tor_command())
@@ -47,7 +49,7 @@ class TestVersion(unittest.TestCase):
     we can parse it.
     """
     
-    test.runner.require_control(self)
+    if test.runner.require_control(self): return
     
     control_socket = test.runner.get_runner().get_tor_socket()
     control_socket.send("GETINFO version")
diff --git a/test/runner.py b/test/runner.py
index 7d053cb..1bf1860 100644
--- a/test/runner.py
+++ b/test/runner.py
@@ -8,6 +8,7 @@ about the tor test instance they're running against.
   RunnerStopped - Runner doesn't have an active tor instance
   TorInaccessable - Tor can't be queried for the information
   
+  skip - skips the current test if we can
   require_control - skips the test unless tor provides a controller endpoint
   require_version - skips the test unless we meet a tor version requirement
   exercise_controller - basic sanity check that a controller connection can be used
@@ -44,6 +45,7 @@ import logging
 import tempfile
 import threading
 
+import stem.prereq
 import stem.socket
 import stem.process
 import stem.version
@@ -99,15 +101,31 @@ class RunnerStopped(Exception):
 class TorInaccessable(Exception):
   "Raised when information is needed from tor but the instance we have is inaccessable"
 
+def skip(test_case, message):
+  """
+  Skips the test if we can. The capability for skipping tests was added in
+  python 2.7 so callers should return after this, so they report 'success' if
+  this method is unavailable.
+  
+  :param unittest.TestCase test_case: test being ran
+  :param str message: message to skip the test with
+  """
+  
+  if stem.prereq.is_python_27():
+    test_case.skipTest(message)
+
 def require_control(test_case):
   """
   Skips the test unless tor provides an endpoint for controllers to attach to.
   
   :param unittest.TestCase test_case: test being ran
+  
+  :returns: True if test should be skipped, False otherwise
   """
   
   if not test.runner.get_runner().is_accessible():
-    test_case.skipTest("(no connection)")
+    skip(test_case, "(no connection)")
+    return True
 
 def require_version(test_case, req_version):
   """
@@ -115,10 +133,13 @@ def require_version(test_case, req_version):
   
   :param unittest.TestCase test_case: test being ran
   :param stem.version.Version req_version: required tor version for the test
+  
+  :returns: True if test should be skipped, False otherwise
   """
   
   if get_runner().get_tor_version() < req_version:
-    test_case.skipTest("(requires %s)" % req_version)
+    skip(test_case, "(requires %s)" % req_version)
+    return True
 
 def only_run_once(test_case, test_name):
   """
@@ -128,10 +149,13 @@ def only_run_once(test_case, test_name):
   
   :param unittest.TestCase test_case: test being ran
   :param str test_name: name of the test being ran
+  
+  :returns: True if test should be skipped, False otherwise
   """
   
   if (test_case, test_name) in RAN_TESTS:
-    test_case.skipTest("(already ran)")
+    skip(test_case, "(already ran)")
+    return True
   else:
     RAN_TESTS.append((test_case, test_name))
 
diff --git a/test/unit/descriptor/server_descriptor.py b/test/unit/descriptor/server_descriptor.py
index 8502b56..2e642af 100644
--- a/test/unit/descriptor/server_descriptor.py
+++ b/test/unit/descriptor/server_descriptor.py
@@ -9,6 +9,7 @@ import unittest
 import stem.prereq
 import stem.descriptor.server_descriptor
 from stem.descriptor.server_descriptor import RelayDescriptor, BridgeDescriptor
+import test.runner
 
 CRYPTO_BLOB = """
 MIGJAoGBAJv5IIWQ+WDWYUdyA/0L8qbIkEVH/cwryZWoIaPAzINfrw1WfNZGtBmg
@@ -314,7 +315,8 @@ class TestServerDescriptor(unittest.TestCase):
     """
     
     if not stem.prereq.is_rsa_available():
-      self.skipTest("(rsa module unavailable)")
+      test.runner.skip(self, "(rsa module unavailable)")
+      return
     
     fingerprint = "4F0C 867D F0EF 6816 0568 C826 838F 482C EA7C FE44"
     desc_text = _make_descriptor({"opt fingerprint": fingerprint})
@@ -328,7 +330,8 @@ class TestServerDescriptor(unittest.TestCase):
     """
     
     if not stem.prereq.is_rsa_available():
-      self.skipTest("(rsa module unavailable)")
+      test.runner.skip(self, "(rsa module unavailable)")
+      return
     
     fingerprint = "4F0C 867D F0EF 6816 0568 C826 838F 482C EA7C FE45"
     desc_text = _make_descriptor({"opt fingerprint": fingerprint})



More information about the tor-commits mailing list