[tor-commits] [stem/master] Making explicit checks for tor accessibility

atagar at torproject.org atagar at torproject.org
Fri Jan 13 17:46:31 UTC 2012


commit 0071fadd8b69eda81cdd9826719037fafdebbb74
Author: Damian Johnson <atagar at torproject.org>
Date:   Fri Jan 13 08:28:32 2012 -0800

    Making explicit checks for tor accessibility
    
    Several 'test/runner.py' functions query against our tor instance. However, in
    some integ tests we don't have any method for doing that. Rather than returning
    a default value I'm raising in those cases, and adding an is_accessible method
    to make our tests more readable.
---
 test/integ/socket/control_message.py |   30 +++++++++--------
 test/runner.py                       |   57 +++++++++++++++++++++++++---------
 2 files changed, 58 insertions(+), 29 deletions(-)

diff --git a/test/integ/socket/control_message.py b/test/integ/socket/control_message.py
index d0c44dc..33a54bf 100644
--- a/test/integ/socket/control_message.py
+++ b/test/integ/socket/control_message.py
@@ -20,13 +20,14 @@ class TestControlMessage(unittest.TestCase):
     Checks message parsing when we have a valid but unauthenticated socket.
     """
     
-    control_socket = test.runner.get_runner().get_tor_socket(False)
-    if not control_socket: self.skipTest("(no control socket)")
+    runner = test.runner.get_runner()
+    if not runner.is_accessible(): self.skipTest("(no control socket)")
     
     # If an unauthenticated connection gets a message besides AUTHENTICATE or
     # PROTOCOLINFO then tor will give an 'Authentication required.' message and
     # hang up.
     
+    control_socket = runner.get_tor_socket(False)
     control_socket.send("GETINFO version")
     
     auth_required_response = control_socket.recv()
@@ -66,8 +67,9 @@ class TestControlMessage(unittest.TestCase):
     Parses the response for a command which doesn't exist.
     """
     
-    control_socket = test.runner.get_runner().get_tor_socket()
-    if not control_socket: self.skipTest("(no control socket)")
+    runner = test.runner.get_runner()
+    if not runner.is_accessible(): self.skipTest("(no control socket)")
+    control_socket = runner.get_tor_socket()
     
     control_socket.send("blarg")
     unrecognized_command_response = control_socket.recv()
@@ -83,8 +85,9 @@ class TestControlMessage(unittest.TestCase):
     Parses the response for a GETINFO query which doesn't exist.
     """
     
-    control_socket = test.runner.get_runner().get_tor_socket()
-    if not control_socket: self.skipTest("(no control socket)")
+    runner = test.runner.get_runner()
+    if not runner.is_accessible(): self.skipTest("(no control socket)")
+    control_socket = runner.get_tor_socket()
     
     control_socket.send("GETINFO blarg")
     unrecognized_key_response = control_socket.recv()
@@ -102,9 +105,8 @@ class TestControlMessage(unittest.TestCase):
     
     runner = test.runner.get_runner()
     torrc_dst = runner.get_torrc_path()
-    
+    if not runner.is_accessible(): self.skipTest("(no control socket)")
     control_socket = runner.get_tor_socket()
-    if not control_socket: self.skipTest("(no control socket)")
     
     control_socket.send("GETINFO config-file")
     config_file_response = control_socket.recv()
@@ -122,9 +124,10 @@ class TestControlMessage(unittest.TestCase):
     
     runner = test.runner.get_runner()
     req_version = stem.version.Requirement.GETINFO_CONFIG_TEXT
-    our_version = runner.get_tor_version()
     
-    if our_version and our_version < req_version:
+    if not runner.is_accessible():
+      self.skipTest("(no control socket)")
+    elif runner.get_tor_version() < req_version:
       self.skipTest("(requires %s)" % req_version)
     
     # We can't be certain of the order, and there may be extra config-text
@@ -142,8 +145,6 @@ class TestControlMessage(unittest.TestCase):
         torrc_contents.append(line)
     
     control_socket = runner.get_tor_socket()
-    if not control_socket: self.skipTest("(no control socket)")
-    
     control_socket.send("GETINFO config-text")
     config_text_response = control_socket.recv()
     
@@ -169,8 +170,9 @@ class TestControlMessage(unittest.TestCase):
     Issues 'SETEVENTS BW' and parses a few events.
     """
     
-    control_socket = test.runner.get_runner().get_tor_socket()
-    if not control_socket: self.skipTest("(no control socket)")
+    runner = test.runner.get_runner()
+    if not runner.is_accessible(): self.skipTest("(no control socket)")
+    control_socket = runner.get_tor_socket()
     
     control_socket.send("SETEVENTS BW")
     setevents_response = control_socket.recv()
diff --git a/test/runner.py b/test/runner.py
index d5f4a91..5841154 100644
--- a/test/runner.py
+++ b/test/runner.py
@@ -10,11 +10,13 @@ Runner - Runtime context for our integration tests.
   |- start - prepares and starts a tor instance for our tests to run against
   |- stop - stops our tor instance and cleans up any temporary files
   |- is_running - checks if our tor test instance is running
+  |- is_accessible - checks if our tor instance can be connected to
   |- is_debugging_prevented - checks if DisableDebuggerAttachment is set
   |- get_test_dir - testing directory path
   |- get_torrc_path - path to our tor instance's torrc
   |- get_torrc_contents - contents of our tor instance's torrc
   |- get_connection_type - method by which controllers can connect to tor
+  |- get_connection_options - connection related options we're running with
   |- get_pid - process id of our tor process
   |- get_tor_socket - provides a socket to the tor instance
   +- get_tor_version - provides the version of tor we're running against
@@ -129,6 +131,10 @@ class RunnerStopped(Exception):
   "Raised when we try to use a Runner that doesn't have an active tor instance"
   pass
 
+class TorInaccessable(Exception):
+  "Raised when information is needed from tor but the instance we have is inaccessable"
+  pass
+
 class Runner:
   def __init__(self):
     self._config = dict(DEFAULT_CONFIG)
@@ -256,6 +262,17 @@ class Runner:
     
     return is_running
   
+  def is_accessible(self):
+    """
+    Checks if our tor instance has a method of being connected to or not.
+    
+    Returns:
+      True if tor has a control socket or port, False otherwise
+    """
+    
+    conn_opts = self.get_connection_options()
+    return OPT_PORT in conn_opts or OPT_SOCKET in conn_opts
+  
   def is_debugging_prevented(self):
     """
     Checks if tor's 'DisableDebuggerAttachment' option is set. This feature has
@@ -263,14 +280,14 @@ class Runner:
     https://trac.torproject.org/projects/tor/ticket/3313
     
     Returns:
-      True if debugger attachment is disallowd, False otherwise, and None if
-      tor can't be checked
+      True if debugger attachment is disallowd, False otherwise
+    
+    Raises:
+      TorInaccessable if this can't be determined
     """
     
     # TODO: replace higher level GETCONF query when we have a controller class
     control_socket = self.get_tor_socket()
-    if control_socket == None: return None
-    
     control_socket.send("GETCONF DisableDebuggerAttachment")
     getconf_response = control_socket.recv()
     control_socket.close()
@@ -349,6 +366,16 @@ class Runner:
     
     return self._connection_type
   
+  def get_connection_options(self):
+    """
+    Provides the connection related options we're running with.
+    
+    Returns:
+      list of connection contstants (test.runner.OPT_*) we're running with
+    """
+    
+    return CONNECTION_OPTS[self.get_connection_type()]
+  
   def get_pid(self):
     """
     Provides the process id of the tor process.
@@ -371,20 +398,19 @@ class Runner:
       authenticate (bool) - if True then the socket is authenticated
     
     Returns:
-      stem.socket.ControlSocket connected with our testing instance, returning
-      None if we either don't have a test instance or it can't be connected to
-    """
+      stem.socket.ControlSocket connected with our testing instance
     
-    connection_type, cookie_path = self.get_connection_type(), self.get_auth_cookie_path()
-    if connection_type == None: return None
+    Raises:
+      TorInaccessable if tor can't be connected to
+    """
     
-    conn_opts = CONNECTION_OPTS[connection_type]
+    conn_opts = self.get_connection_options()
     
     if OPT_PORT in conn_opts:
       control_socket = stem.socket.ControlPort(control_port = CONTROL_PORT)
     elif OPT_SOCKET in conn_opts:
       control_socket = stem.socket.ControlSocketFile(CONTROL_SOCKET_PATH)
-    else: return None
+    else: raise TorInaccessable("Unable to connect to tor")
     
     if authenticate:
       stem.connection.authenticate(control_socket, CONTROL_PASSWORD)
@@ -396,15 +422,16 @@ class Runner:
     Queries our test instance for tor's version.
     
     Returns:
-      stem.version.Version for our test instance, None if we're unable to
-      connect to it
+      stem.version.Version for our test instance
+    
+    Raises:
+      TorInaccessable if this can't be determined
     """
     
     # TODO: replace with higher level functions when we've completed a basic
     # controller class
     
     control_socket = self.get_tor_socket()
-    if not control_socket: return None
     
     control_socket.send("GETINFO version")
     version_response = control_socket.recv()
@@ -466,7 +493,7 @@ class Runner:
     # resides in is only accessable by the tor user (and refuses to finish
     # starting if it isn't).
     
-    if OPT_SOCKET in CONNECTION_OPTS[self._connection_type]:
+    if OPT_SOCKET in self.get_connection_options():
       try:
         socket_dir = os.path.dirname(CONTROL_SOCKET_PATH)
         _print_status("  making control socket directory (%s)... " % socket_dir, STATUS_ATTR, quiet)





More information about the tor-commits mailing list