[tor-commits] [stem/master] Refactoring system integ tests

atagar at torproject.org atagar at torproject.org
Mon Jan 30 01:40:05 UTC 2012


commit 5e81a0b546413f6ef21266cb74b81e9be4c6a27c
Author: Damian Johnson <atagar at torproject.org>
Date:   Sun Jan 29 17:31:53 2012 -0800

    Refactoring system integ tests
    
    This is the last of the integration tests to be cleaned up. It's also the last
    user of the system module's CALL_MOCKING so now we can get rid of it - hazaa!
---
 test/integ/connection/protocolinfo.py |   14 +----
 test/integ/util/system.py             |  124 +++++++++++++++++++--------------
 test/mocking.py                       |   19 +++++
 test/runner.py                        |   14 ++---
 4 files changed, 97 insertions(+), 74 deletions(-)

diff --git a/test/integ/connection/protocolinfo.py b/test/integ/connection/protocolinfo.py
index b572aee..e0e8805 100644
--- a/test/integ/connection/protocolinfo.py
+++ b/test/integ/connection/protocolinfo.py
@@ -10,19 +10,7 @@ import stem.socket
 import stem.connection
 import stem.util.system
 import test.mocking as mocking
-
-def filter_system_call(prefixes):
-  """
-  Provides a functor that passes calls on to the stem.util.system.call()
-  function if it matches one of the prefixes, and acts as a no-op otherwise.
-  """
-  
-  def _filter_system_call(command):
-    for prefix in prefixes:
-      if command.startswith(prefix):
-        return stem.util.system.call(command)
-  
-  return _filter_system_call
+from test.integ.util.system import filter_system_call
 
 class TestProtocolInfo(unittest.TestCase):
   def setUp(self):
diff --git a/test/integ/util/system.py b/test/integ/util/system.py
index 9295e9b..f9c00a6 100644
--- a/test/integ/util/system.py
+++ b/test/integ/util/system.py
@@ -1,5 +1,5 @@
 """
-Integratnio tests for the stem.util.system functions against the tor process
+Integration tests for the stem.util.system functions against the tor process
 that we're running.
 """
 
@@ -7,8 +7,30 @@ import os
 import getpass
 import unittest
 
-import test.runner
 import stem.util.system
+import test.runner
+import test.mocking as mocking
+
+def filter_system_call(prefixes):
+  """
+  Provides a functor that passes calls on to the stem.util.system.call()
+  function if it matches one of the prefixes, and acts as a no-op otherwise.
+  """
+  
+  def _filter_system_call(command):
+    for prefix in prefixes:
+      if command.startswith(prefix):
+        real_call_function = mocking.get_real_function(stem.util.system.call)
+        return real_call_function(command)
+  
+  return _filter_system_call
+
+def _has_port():
+  """
+  True if our test runner has a control port, False otherwise.
+  """
+  
+  return test.runner.Torrc.PORT in test.runner.get_runner().get_options()
 
 class TestSystem(unittest.TestCase):
   is_extra_tor_running = None
@@ -27,10 +49,9 @@ class TestSystem(unittest.TestCase):
         ps_results = stem.util.system.call(stem.util.system.GET_PID_BY_NAME_PS_BSD)
         results = [r for r in ps_results if r.endswith(" tor")]
         self.is_extra_tor_running = len(results) > 1
-        
+  
   def tearDown(self):
-    # resets call mocking back to being disabled
-    stem.util.system.CALL_MOCKING = None
+    mocking.revert_mocking()
   
   def test_is_available(self):
     """
@@ -60,8 +81,8 @@ class TestSystem(unittest.TestCase):
     if self.is_extra_tor_running:
       self.skipTest("(multiple tor instances)")
     
-    runner = test.runner.get_runner()
-    self.assertEquals(runner.get_pid(), stem.util.system.get_pid_by_name("tor"))
+    tor_pid = test.runner.get_runner().get_pid()
+    self.assertEquals(tor_pid, stem.util.system.get_pid_by_name("tor"))
     self.assertEquals(None, stem.util.system.get_pid_by_name("blarg_and_stuff"))
   
   def test_get_pid_by_name_pgrep(self):
@@ -75,7 +96,10 @@ class TestSystem(unittest.TestCase):
       self.skipTest("(pgrep unavailable)")
     
     pgrep_prefix = stem.util.system.GET_PID_BY_NAME_PGREP % ""
-    self._run_pid_test(pgrep_prefix, stem.util.system.get_pid_by_name, "tor")
+    mocking.mock(stem.util.system.call, filter_system_call([pgrep_prefix]))
+    
+    tor_pid = test.runner.get_runner().get_pid()
+    self.assertEquals(tor_pid, stem.util.system.get_pid_by_name("tor"))
   
   def test_get_pid_by_name_pidof(self):
     """
@@ -88,7 +112,10 @@ class TestSystem(unittest.TestCase):
       self.skipTest("(pidof unavailable)")
     
     pidof_prefix = stem.util.system.GET_PID_BY_NAME_PIDOF % ""
-    self._run_pid_test(pidof_prefix, stem.util.system.get_pid_by_name, "tor")
+    mocking.mock(stem.util.system.call, filter_system_call([pidof_prefix]))
+    
+    tor_pid = test.runner.get_runner().get_pid()
+    self.assertEquals(tor_pid, stem.util.system.get_pid_by_name("tor"))
   
   def test_get_pid_by_name_ps_linux(self):
     """
@@ -103,7 +130,10 @@ class TestSystem(unittest.TestCase):
       self.skipTest("(linux only)")
     
     ps_prefix = stem.util.system.GET_PID_BY_NAME_PS_LINUX % ""
-    self._run_pid_test(ps_prefix, stem.util.system.get_pid_by_name, "tor")
+    mocking.mock(stem.util.system.call, filter_system_call([ps_prefix]))
+    
+    tor_pid = test.runner.get_runner().get_pid()
+    self.assertEquals(tor_pid, stem.util.system.get_pid_by_name("tor"))
   
   def test_get_pid_by_name_ps_bsd(self):
     """
@@ -117,8 +147,11 @@ class TestSystem(unittest.TestCase):
     elif not stem.util.system.is_bsd():
       self.skipTest("(bsd only)")
     
-    ps_cmd = stem.util.system.GET_PID_BY_NAME_PS_BSD
-    self._run_pid_test(ps_cmd, stem.util.system.get_pid_by_name, "tor")
+    ps_prefix = stem.util.system.GET_PID_BY_NAME_PS_BSD
+    mocking.mock(stem.util.system.call, filter_system_call([ps_prefix]))
+    
+    tor_pid = test.runner.get_runner().get_pid()
+    self.assertEquals(tor_pid, stem.util.system.get_pid_by_name("tor"))
   
   def test_get_pid_by_name_lsof(self):
     """
@@ -130,13 +163,14 @@ class TestSystem(unittest.TestCase):
       self.skipTest("(multiple tor instances)")
     elif not stem.util.system.is_available("lsof"):
       self.skipTest("(lsof unavailable)")
-    elif not runner.is_accessible():
-      self.skipTest("(unable to check for DisableDebuggerAttachment)")
     elif not runner.is_ptraceable():
       self.skipTest("(DisableDebuggerAttachment is set)")
     
     lsof_prefix = stem.util.system.GET_PID_BY_NAME_LSOF % ""
-    self._run_pid_test(lsof_prefix, stem.util.system.get_pid_by_name, "tor")
+    mocking.mock(stem.util.system.call, filter_system_call([lsof_prefix]))
+    
+    tor_pid = test.runner.get_runner().get_pid()
+    self.assertEquals(tor_pid, stem.util.system.get_pid_by_name("tor"))
   
   def test_get_pid_by_port(self):
     """
@@ -144,7 +178,7 @@ class TestSystem(unittest.TestCase):
     """
     
     runner = test.runner.get_runner()
-    if not self._has_port():
+    if not _has_port():
       self.skipTest("(test instance has no port)")
     elif not runner.is_ptraceable():
       self.skipTest("(DisableDebuggerAttachment is set)")
@@ -159,7 +193,7 @@ class TestSystem(unittest.TestCase):
     """
     
     runner = test.runner.get_runner()
-    if not self._has_port():
+    if not _has_port():
       self.skipTest("(test instance has no port)")
     elif not stem.util.system.is_available("netstat"):
       self.skipTest("(netstat unavailable)")
@@ -168,8 +202,11 @@ class TestSystem(unittest.TestCase):
     elif not runner.is_ptraceable():
       self.skipTest("(DisableDebuggerAttachment is set)")
     
-    netstat_cmd = stem.util.system.GET_PID_BY_PORT_NETSTAT
-    self._run_pid_test(netstat_cmd, stem.util.system.get_pid_by_port, test.runner.CONTROL_PORT)
+    netstat_prefix = stem.util.system.GET_PID_BY_PORT_NETSTAT
+    mocking.mock(stem.util.system.call, filter_system_call([netstat_prefix]))
+    
+    tor_pid = test.runner.get_runner().get_pid()
+    self.assertEquals(tor_pid, stem.util.system.get_pid_by_port(test.runner.CONTROL_PORT))
   
   def test_get_pid_by_port_sockstat(self):
     """
@@ -177,7 +214,7 @@ class TestSystem(unittest.TestCase):
     """
     
     runner = test.runner.get_runner()
-    if not self._has_port():
+    if not _has_port():
       self.skipTest("(test instance has no port)")
     elif not stem.util.system.is_available("sockstat"):
       self.skipTest("(sockstat unavailable)")
@@ -187,7 +224,10 @@ class TestSystem(unittest.TestCase):
       self.skipTest("(DisableDebuggerAttachment is set)")
     
     sockstat_prefix = stem.util.system.GET_PID_BY_PORT_SOCKSTAT % ""
-    self._run_pid_test(sockstat_prefix, stem.util.system.get_pid_by_port, test.runner.CONTROL_PORT)
+    mocking.mock(stem.util.system.call, filter_system_call([sockstat_prefix]))
+    
+    tor_pid = test.runner.get_runner().get_pid()
+    self.assertEquals(tor_pid, stem.util.system.get_pid_by_port(test.runner.CONTROL_PORT))
   
   def test_get_pid_by_port_lsof(self):
     """
@@ -195,15 +235,18 @@ class TestSystem(unittest.TestCase):
     """
     
     runner = test.runner.get_runner()
-    if not self._has_port():
+    if not _has_port():
       self.skipTest("(test instance has no port)")
     elif not stem.util.system.is_available("lsof"):
       self.skipTest("(lsof unavailable)")
     elif not runner.is_ptraceable():
       self.skipTest("(DisableDebuggerAttachment is set)")
     
-    lsof_cmd = stem.util.system.GET_PID_BY_PORT_LSOF
-    self._run_pid_test(lsof_cmd, stem.util.system.get_pid_by_port, test.runner.CONTROL_PORT)
+    lsof_prefix = stem.util.system.GET_PID_BY_PORT_LSOF
+    mocking.mock(stem.util.system.call, filter_system_call([lsof_prefix]))
+    
+    tor_pid = test.runner.get_runner().get_pid()
+    self.assertEquals(tor_pid, stem.util.system.get_pid_by_port(test.runner.CONTROL_PORT))
   
   def test_get_pid_by_open_file(self):
     """
@@ -226,12 +269,11 @@ class TestSystem(unittest.TestCase):
     
     runner = test.runner.get_runner()
     
-    if not runner.is_accessible():
-      self.skipTest("(unable to check for DisableDebuggerAttachment)")
-    elif not runner.is_ptraceable():
+    if not runner.is_ptraceable():
       self.skipTest("(DisableDebuggerAttachment is set)")
     
-    self.assertEquals(runner.get_tor_cwd(), stem.util.system.get_cwd(runner.get_pid()))
+    runner_pid, tor_cwd = runner.get_pid(), runner.get_tor_cwd()
+    self.assertEquals(tor_cwd, stem.util.system.get_cwd(runner_pid))
     self.assertEquals(None, stem.util.system.get_cwd(99999))
   
   def test_get_cwd_pwdx(self):
@@ -242,14 +284,12 @@ class TestSystem(unittest.TestCase):
     runner = test.runner.get_runner()
     if not stem.util.system.is_available("pwdx"):
       self.skipTest("(pwdx unavailable)")
-    elif not runner.is_accessible():
-      self.skipTest("(unable to check for DisableDebuggerAttachment)")
     elif not runner.is_ptraceable():
       self.skipTest("(DisableDebuggerAttachment is set)")
     
     # filter the call function to only allow this command
     pwdx_prefix = stem.util.system.GET_CWD_PWDX % ""
-    stem.util.system.CALL_MOCKING = lambda cmd: cmd.startswith(pwdx_prefix)
+    mocking.mock(stem.util.system.call, filter_system_call([pwdx_prefix]))
     
     runner_pid, tor_cwd = runner.get_pid(), runner.get_tor_cwd()
     self.assertEquals(tor_cwd, stem.util.system.get_cwd(runner_pid))
@@ -262,14 +302,12 @@ class TestSystem(unittest.TestCase):
     runner = test.runner.get_runner()
     if not stem.util.system.is_available("lsof"):
       self.skipTest("(lsof unavailable)")
-    elif not runner.is_accessible():
-      self.skipTest("(unable to check for DisableDebuggerAttachment)")
     elif not runner.is_ptraceable():
       self.skipTest("(DisableDebuggerAttachment is set)")
     
     # filter the call function to only allow this command
     lsof_prefix = "lsof -a -p "
-    stem.util.system.CALL_MOCKING = lambda cmd: cmd.startswith(lsof_prefix)
+    mocking.mock(stem.util.system.call, filter_system_call([lsof_prefix]))
     
     runner_pid, tor_cwd = runner.get_pid(), runner.get_tor_cwd()
     self.assertEquals(tor_cwd, stem.util.system.get_cwd(runner_pid))
@@ -297,22 +335,4 @@ class TestSystem(unittest.TestCase):
     self.assertEquals(home_dir, stem.util.system.expand_path("~/"))
     self.assertEquals(home_dir, stem.util.system.expand_path("~%s" % username))
     self.assertEquals(os.path.join(home_dir, "foo"), stem.util.system.expand_path("~%s/foo" % username))
-  
-  def _run_pid_test(self, cmd_prefix, test_function, arg):
-    """
-    Runs a get_pid_by_* test with the given inputs.
-    """
-    
-    # filter the call function to only allow this command
-    stem.util.system.CALL_MOCKING = lambda cmd: cmd.startswith(cmd_prefix)
-    
-    runner_pid = test.runner.get_runner().get_pid()
-    self.assertEquals(runner_pid, test_function(arg))
-  
-  def _has_port(self):
-    """
-    True if our test runner has a control port, False otherwise.
-    """
-    
-    return test.runner.Torrc.PORT in test.runner.get_runner().get_options()
 
diff --git a/test/mocking.py b/test/mocking.py
index 0d01a60..30ba490 100644
--- a/test/mocking.py
+++ b/test/mocking.py
@@ -6,6 +6,7 @@ calling 'revert_mocking'.
 
 mock - replaces a function with an alternative implementation
 revert_mocking - reverts any changes made by the mock function
+get_real_function - provides the non-mocked version of a function
 
 Mocking Functions
   no_op           - does nothing
@@ -98,6 +99,24 @@ def revert_mocking():
   
   MOCK_STATE.clear()
 
+def get_real_function(function):
+  """
+  Provides the original, non-mocked implementation for a function. This simply
+  returns the current implementation if it isn't being mocked.
+  
+  Arguments:
+    function (function) - function to look up the original implementation of
+  
+  Returns:
+    original implementation of the function
+  """
+  
+  if "mock_id" in function.__dict__:
+    mocking_id = function.__dict__["mock_id"]
+    return MOCK_STATE[mocking_id][2]
+  else:
+    return function
+
 def get_message(content, reformat = True):
   """
   Provides a ControlMessage with content modified to be parsable. This makes
diff --git a/test/runner.py b/test/runner.py
index 3cf5542..07a54fd 100644
--- a/test/runner.py
+++ b/test/runner.py
@@ -276,18 +276,14 @@ class Runner:
     
     Returns:
       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()
-    control_socket.send("GETCONF DisableDebuggerAttachment")
-    getconf_response = control_socket.recv()
-    control_socket.close()
+    # If we're running a tor version where ptrace is disabled and we didn't
+    # set 'DisableDebuggerAttachment=1' then we can infer that it's disabled.
     
-    return str(getconf_response) != "DisableDebuggerAttachment=1"
+    tor_version = self.get_tor_version()
+    has_option = tor_version >= stem.version.Requirement.TORRC_DISABLE_DEBUGGER_ATTACHMENT
+    return not has_option or Torrc.PTRACE in self.get_options()
   
   def get_options(self):
     """





More information about the tor-commits mailing list