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

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


commit f38ad0811290b51b99475de28628895a663e7dec
Author: Damian Johnson <atagar at torproject.org>
Date:   Sun Jan 29 14:40:27 2012 -0800

    Refactoring ControlMessage integ tests
    
    Besides the normal cleanup I'm pushing most of the skipTest checks into the
    runner module. The advantage of this is that it simplifies tests a little more
    and allows a standardized skip message rather than having each module provide
    their own for the same thing.
---
 test/integ/connection/authentication.py |    4 +-
 test/integ/connection/connect.py        |    4 +-
 test/integ/connection/protocolinfo.py   |    4 +-
 test/integ/socket/control_message.py    |  146 +++++++++++++------------------
 test/integ/version.py                   |   13 +--
 test/runner.py                          |   54 ++++++++---
 6 files changed, 106 insertions(+), 119 deletions(-)

diff --git a/test/integ/connection/authentication.py b/test/integ/connection/authentication.py
index cc36c66..0762b23 100644
--- a/test/integ/connection/authentication.py
+++ b/test/integ/connection/authentication.py
@@ -78,9 +78,7 @@ def _get_auth_failure_message(auth_type):
 
 class TestAuthenticate(unittest.TestCase):
   def setUp(self):
-    # none of these tests apply if there's no control connection
-    if not test.runner.get_runner().is_accessible():
-      self.skipTest("(no connection)")
+    test.runner.require_control(self)
   
   def test_authenticate_general(self):
     """
diff --git a/test/integ/connection/connect.py b/test/integ/connection/connect.py
index ca3cf41..9b6337a 100644
--- a/test/integ/connection/connect.py
+++ b/test/integ/connection/connect.py
@@ -11,9 +11,7 @@ import test.runner
 
 class TestConnect(unittest.TestCase):
   def setUp(self):
-    # none of these tests apply if there's no control connection
-    if not test.runner.get_runner().is_accessible():
-      self.skipTest("(no connection)")
+    test.runner.require_control(self)
     
     # prevents the function from printing to the real stdout
     self.original_stdout = sys.stdout
diff --git a/test/integ/connection/protocolinfo.py b/test/integ/connection/protocolinfo.py
index a0e1699..b572aee 100644
--- a/test/integ/connection/protocolinfo.py
+++ b/test/integ/connection/protocolinfo.py
@@ -26,9 +26,7 @@ def filter_system_call(prefixes):
 
 class TestProtocolInfo(unittest.TestCase):
   def setUp(self):
-    if not test.runner.get_runner().is_accessible():
-      self.skipTest("(no connection)")
-    
+    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())
   
diff --git a/test/integ/socket/control_message.py b/test/integ/socket/control_message.py
index ec99edb..ce25c8f 100644
--- a/test/integ/socket/control_message.py
+++ b/test/integ/socket/control_message.py
@@ -3,7 +3,6 @@ Integration tests for the stem.socket.ControlMessage class.
 """
 
 import re
-import socket
 import unittest
 
 import stem.socket
@@ -11,19 +10,19 @@ 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.
     """
     
-    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 = test.runner.get_runner().get_tor_socket(False)
     control_socket.send("GETINFO version")
     
     auth_required_response = control_socket.recv()
@@ -63,36 +62,26 @@ class TestControlMessage(unittest.TestCase):
     Parses the response for a command which doesn't exist.
     """
     
-    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()
-    self.assertEquals('Unrecognized command "blarg"', str(unrecognized_command_response))
-    self.assertEquals(['Unrecognized command "blarg"'], list(unrecognized_command_response))
-    self.assertEquals('510 Unrecognized command "blarg"\r\n', unrecognized_command_response.raw_content())
-    self.assertEquals([('510', ' ', 'Unrecognized command "blarg"')], unrecognized_command_response.content())
-    
-    control_socket.close()
+    with test.runner.get_runner().get_tor_socket() as control_socket:
+      control_socket.send("blarg")
+      unrecognized_command_response = control_socket.recv()
+      self.assertEquals('Unrecognized command "blarg"', str(unrecognized_command_response))
+      self.assertEquals(['Unrecognized command "blarg"'], list(unrecognized_command_response))
+      self.assertEquals('510 Unrecognized command "blarg"\r\n', unrecognized_command_response.raw_content())
+      self.assertEquals([('510', ' ', 'Unrecognized command "blarg"')], unrecognized_command_response.content())
   
   def test_invalid_getinfo(self):
     """
     Parses the response for a GETINFO query which doesn't exist.
     """
     
-    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()
-    self.assertEquals('Unrecognized key "blarg"', str(unrecognized_key_response))
-    self.assertEquals(['Unrecognized key "blarg"'], list(unrecognized_key_response))
-    self.assertEquals('552 Unrecognized key "blarg"\r\n', unrecognized_key_response.raw_content())
-    self.assertEquals([('552', ' ', 'Unrecognized key "blarg"')], unrecognized_key_response.content())
-    
-    control_socket.close()
+    with test.runner.get_runner().get_tor_socket() as control_socket:
+      control_socket.send("GETINFO blarg")
+      unrecognized_key_response = control_socket.recv()
+      self.assertEquals('Unrecognized key "blarg"', str(unrecognized_key_response))
+      self.assertEquals(['Unrecognized key "blarg"'], list(unrecognized_key_response))
+      self.assertEquals('552 Unrecognized key "blarg"\r\n', unrecognized_key_response.raw_content())
+      self.assertEquals([('552', ' ', 'Unrecognized key "blarg"')], unrecognized_key_response.content())
   
   def test_getinfo_config_file(self):
     """
@@ -101,30 +90,22 @@ 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()
-    
-    control_socket.send("GETINFO config-file")
-    config_file_response = control_socket.recv()
-    self.assertEquals("config-file=%s\nOK" % torrc_dst, str(config_file_response))
-    self.assertEquals(["config-file=%s" % torrc_dst, "OK"], list(config_file_response))
-    self.assertEquals("250-config-file=%s\r\n250 OK\r\n" % torrc_dst, config_file_response.raw_content())
-    self.assertEquals([("250", "-", "config-file=%s" % torrc_dst), ("250", " ", "OK")], config_file_response.content())
     
-    control_socket.close()
+    with runner.get_tor_socket() as control_socket:
+      control_socket.send("GETINFO config-file")
+      config_file_response = control_socket.recv()
+      self.assertEquals("config-file=%s\nOK" % torrc_dst, str(config_file_response))
+      self.assertEquals(["config-file=%s" % torrc_dst, "OK"], list(config_file_response))
+      self.assertEquals("250-config-file=%s\r\n250 OK\r\n" % torrc_dst, config_file_response.raw_content())
+      self.assertEquals([("250", "-", "config-file=%s" % torrc_dst), ("250", " ", "OK")], config_file_response.content())
   
   def test_getinfo_config_text(self):
     """
     Parses the 'GETINFO config-text' response.
     """
     
+    test.runner.require_version(self, stem.version.Requirement.GETINFO_CONFIG_TEXT)
     runner = test.runner.get_runner()
-    req_version = stem.version.Requirement.GETINFO_CONFIG_TEXT
-    
-    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
     # entries as per...
@@ -140,50 +121,43 @@ class TestControlMessage(unittest.TestCase):
       if line and not line.startswith("#"):
         torrc_contents.append(line)
     
-    control_socket = runner.get_tor_socket()
-    control_socket.send("GETINFO config-text")
-    config_text_response = control_socket.recv()
-    
-    # the response should contain two entries, the first being a data response
-    self.assertEqual(2, len(list(config_text_response)))
-    self.assertEqual("OK", list(config_text_response)[1])
-    self.assertEqual(("250", " ", "OK"), config_text_response.content()[1])
-    self.assertTrue(config_text_response.raw_content().startswith("250+config-text=\r\n"))
-    self.assertTrue(config_text_response.raw_content().endswith("\r\n.\r\n250 OK\r\n"))
-    self.assertTrue(str(config_text_response).startswith("config-text=\n"))
-    self.assertTrue(str(config_text_response).endswith("\nOK"))
-    
-    for torrc_entry in torrc_contents:
-      self.assertTrue("\n%s\n" % torrc_entry in str(config_text_response))
-      self.assertTrue(torrc_entry in list(config_text_response)[0])
-      self.assertTrue("%s\r\n" % torrc_entry in config_text_response.raw_content())
-      self.assertTrue("%s" % torrc_entry in config_text_response.content()[0][2])
-    
-    control_socket.close()
+    with runner.get_tor_socket() as control_socket:
+      control_socket.send("GETINFO config-text")
+      config_text_response = control_socket.recv()
+      
+      # the response should contain two entries, the first being a data response
+      self.assertEqual(2, len(list(config_text_response)))
+      self.assertEqual("OK", list(config_text_response)[1])
+      self.assertEqual(("250", " ", "OK"), config_text_response.content()[1])
+      self.assertTrue(config_text_response.raw_content().startswith("250+config-text=\r\n"))
+      self.assertTrue(config_text_response.raw_content().endswith("\r\n.\r\n250 OK\r\n"))
+      self.assertTrue(str(config_text_response).startswith("config-text=\n"))
+      self.assertTrue(str(config_text_response).endswith("\nOK"))
+      
+      for torrc_entry in torrc_contents:
+        self.assertTrue("\n%s\n" % torrc_entry in str(config_text_response))
+        self.assertTrue(torrc_entry in list(config_text_response)[0])
+        self.assertTrue("%s\r\n" % torrc_entry in config_text_response.raw_content())
+        self.assertTrue("%s" % torrc_entry in config_text_response.content()[0][2])
   
   def test_bw_event(self):
     """
-    Issues 'SETEVENTS BW' and parses a few events.
+    Issues 'SETEVENTS BW' and parses a couple events.
     """
     
-    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()
-    self.assertEquals("OK", str(setevents_response))
-    self.assertEquals(["OK"], list(setevents_response))
-    self.assertEquals("250 OK\r\n", setevents_response.raw_content())
-    self.assertEquals([("250", " ", "OK")], setevents_response.content())
-    
-    # Tor will emit a BW event once per second. Parsing two of them.
-    
-    for _ in range(2):
-      bw_event = control_socket.recv()
-      self.assertTrue(re.match("BW [0-9]+ [0-9]+", str(bw_event)))
-      self.assertTrue(re.match("650 BW [0-9]+ [0-9]+\r\n", bw_event.raw_content()))
-      self.assertEquals(("650", " "), bw_event.content()[0][:2])
-    
-    control_socket.close()
+    with test.runner.get_runner().get_tor_socket() as control_socket:
+      control_socket.send("SETEVENTS BW")
+      setevents_response = control_socket.recv()
+      self.assertEquals("OK", str(setevents_response))
+      self.assertEquals(["OK"], list(setevents_response))
+      self.assertEquals("250 OK\r\n", setevents_response.raw_content())
+      self.assertEquals([("250", " ", "OK")], setevents_response.content())
+      
+      # Tor will emit a BW event once per second. Parsing two of them.
+      
+      for _ in range(2):
+        bw_event = control_socket.recv()
+        self.assertTrue(re.match("BW [0-9]+ [0-9]+", str(bw_event)))
+        self.assertTrue(re.match("650 BW [0-9]+ [0-9]+\r\n", bw_event.raw_content()))
+        self.assertEquals(("650", " "), bw_event.content()[0][:2])
 
diff --git a/test/integ/version.py b/test/integ/version.py
index e344ef8..833cbd2 100644
--- a/test/integ/version.py
+++ b/test/integ/version.py
@@ -35,11 +35,9 @@ class TestVersion(unittest.TestCase):
     test instance provides.
     """
     
-    runner = test.runner.get_runner()
-    
-    if not runner.is_accessible():
-      self.skipTest("(no connection)")
+    test.runner.require_control(self)
     
+    runner = test.runner.get_runner()
     system_tor_version = stem.version.get_system_tor_version(runner.get_tor_command())
     self.assertEquals(runner.get_tor_version(), system_tor_version)
   
@@ -49,12 +47,9 @@ class TestVersion(unittest.TestCase):
     we can parse it.
     """
     
-    runner = test.runner.get_runner()
-    
-    if not runner.is_accessible():
-      self.skipTest("(no connection)")
+    test.runner.require_control(self)
     
-    control_socket = runner.get_tor_socket()
+    control_socket = test.runner.get_runner().get_tor_socket()
     control_socket.send("GETINFO version")
     version_response = control_socket.recv()
     control_socket.close()
diff --git a/test/runner.py b/test/runner.py
index 0e71ade..3cf5542 100644
--- a/test/runner.py
+++ b/test/runner.py
@@ -6,6 +6,8 @@ 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
 
+require_control - skips the test unless tor provides a controller endpoint
+require_version - skips the test unless we meet a tor version requirement
 exercise_socket - Does a basic sanity check that a control socket can be used
 
 get_runner - Singleton for fetching our runtime context.
@@ -86,13 +88,36 @@ class TorInaccessable(Exception):
   "Raised when information is needed from tor but the instance we have is inaccessable"
   pass
 
+def require_control(test_case):
+  """
+  Skips the test unless tor provides an endpoint for controllers to attach to.
+  
+  Arguments:
+    test_case (unittest.TestCase) - test being ran
+  """
+  
+  if not test.runner.get_runner().is_accessible():
+    test_case.skipTest("(no connection)")
+
+def require_version(test_case, req_version):
+  """
+  Skips the test unless we meet the required version.
+  
+  Arguments:
+    test_case (unittest.TestCase) - test being ran
+    req_version (stem.version.Version) - required tor version for the test
+  """
+  
+  if get_runner().get_tor_version() < req_version:
+    test_case.skipTest("(requires %s)" % req_version)
+
 def exercise_socket(test_case, control_socket):
   """
   Checks that we can now use the socket by issuing a 'GETINFO config-file'
   query.
   
   Arguments:
-    test_case (unittest.TestCase) - unit testing case being ran
+    test_case (unittest.TestCase) - test being ran
     control_socket (stem.socket.ControlSocket) - socket to be tested
   """
   
@@ -380,22 +405,21 @@ class Runner:
     
     Returns:
       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()
-    
-    control_socket.send("GETINFO version")
-    version_response = control_socket.recv()
-    control_socket.close()
-    
-    tor_version = list(version_response)[0][8:]
-    return stem.version.Version(tor_version)
+    try:
+      # TODO: replace with higher level functions when we've completed a basic
+      # controller class
+      control_socket = self.get_tor_socket()
+      
+      control_socket.send("GETINFO version")
+      version_response = control_socket.recv()
+      control_socket.close()
+      
+      tor_version = list(version_response)[0][8:]
+      return stem.version.Version(tor_version)
+    except TorInaccessable:
+      return stem.version.get_system_tor_version(self.get_tor_command())
   
   def get_tor_command(self):
     """





More information about the tor-commits mailing list