[tor-commits] [stem/master] @only_run_once decorator

atagar at torproject.org atagar at torproject.org
Sat Feb 21 22:08:00 UTC 2015


commit 7232e79de7e0fc0886b836387f7a530627b0c383
Author: Damian Johnson <atagar at torproject.org>
Date:   Sat Feb 21 13:46:17 2015 -0800

    @only_run_once decorator
---
 test/integ/descriptor/extrainfo_descriptor.py |    8 ++----
 test/integ/descriptor/microdescriptor.py      |    6 ++--
 test/integ/descriptor/networkstatus.py        |   14 +++-------
 test/integ/descriptor/remote.py               |   37 ++++++++-----------------
 test/integ/descriptor/server_descriptor.py    |    8 ++----
 test/integ/process.py                         |   20 ++++---------
 test/runner.py                                |   19 ++++++-------
 7 files changed, 40 insertions(+), 72 deletions(-)

diff --git a/test/integ/descriptor/extrainfo_descriptor.py b/test/integ/descriptor/extrainfo_descriptor.py
index cfbc1e5..d102fea 100644
--- a/test/integ/descriptor/extrainfo_descriptor.py
+++ b/test/integ/descriptor/extrainfo_descriptor.py
@@ -8,8 +8,11 @@ import unittest
 import stem.descriptor
 import test.runner
 
+from test.runner import only_run_once
+
 
 class TestExtraInfoDescriptor(unittest.TestCase):
+  @only_run_once
   def test_cached_descriptor(self):
     """
     Parses the cached descriptor file in our data directory, checking that it
@@ -17,11 +20,6 @@ class TestExtraInfoDescriptor(unittest.TestCase):
     additions.
     """
 
-    # lengthy test and uneffected by targets, so only run once
-
-    if test.runner.only_run_once(self):
-      return
-
     descriptor_path = test.runner.get_runner().get_test_dir('cached-extrainfo')
 
     if not os.path.exists(descriptor_path):
diff --git a/test/integ/descriptor/microdescriptor.py b/test/integ/descriptor/microdescriptor.py
index 0652587..ebd0287 100644
--- a/test/integ/descriptor/microdescriptor.py
+++ b/test/integ/descriptor/microdescriptor.py
@@ -8,8 +8,11 @@ import unittest
 import stem.descriptor
 import test.runner
 
+from test.runner import only_run_once
+
 
 class TestMicrodescriptor(unittest.TestCase):
+  @only_run_once
   def test_cached_microdescriptors(self):
     """
     Parses the cached microdescriptor file in our data directory, checking that
@@ -17,9 +20,6 @@ class TestMicrodescriptor(unittest.TestCase):
     descriptor additions.
     """
 
-    if test.runner.only_run_once(self):
-      return
-
     descriptor_path = test.runner.get_runner().get_test_dir('cached-microdescs')
 
     if not os.path.exists(descriptor_path):
diff --git a/test/integ/descriptor/networkstatus.py b/test/integ/descriptor/networkstatus.py
index 6c29158..8f97b26 100644
--- a/test/integ/descriptor/networkstatus.py
+++ b/test/integ/descriptor/networkstatus.py
@@ -11,18 +11,16 @@ import stem.descriptor.networkstatus
 import stem.version
 import test.runner
 
+from test.runner import only_run_once
+
 
 class TestNetworkStatus(unittest.TestCase):
+  @only_run_once
   def test_cached_consensus(self):
     """
     Parses the cached-consensus file in our data directory.
     """
 
-    # lengthy test and uneffected by targets, so only run once
-
-    if test.runner.only_run_once(self):
-      return
-
     consensus_path = test.runner.get_runner().get_test_dir('cached-consensus')
 
     if not os.path.exists(consensus_path):
@@ -57,16 +55,12 @@ class TestNetworkStatus(unittest.TestCase):
 
     self.assertTrue(count > 100)
 
+  @only_run_once
   def test_cached_microdesc_consensus(self):
     """
     Parses the cached-microdesc-consensus file in our data directory.
     """
 
-    # lengthy test and uneffected by targets, so only run once
-
-    if test.runner.only_run_once(self):
-      return
-
     consensus_path = test.runner.get_runner().get_test_dir('cached-microdesc-consensus')
 
     if not os.path.exists(consensus_path):
diff --git a/test/integ/descriptor/remote.py b/test/integ/descriptor/remote.py
index cc7d4cb..78b1add 100644
--- a/test/integ/descriptor/remote.py
+++ b/test/integ/descriptor/remote.py
@@ -13,20 +13,21 @@ import stem.descriptor.router_status_entry
 import stem.descriptor.server_descriptor
 import test.runner
 
-from test.runner import require_online
+from test.runner import (
+  require_online,
+  only_run_once,
+)
 
 
 class TestDescriptorDownloader(unittest.TestCase):
   @require_online
+  @only_run_once
   def test_authorities_are_up_to_date(self):
     """
     Check that our hardcoded directory authority data matches the present
     consensus.
     """
 
-    if test.runner.only_run_once(self):
-      return
-
     downloader = stem.descriptor.remote.DescriptorDownloader()
     consensus = downloader.get_consensus(document_handler = stem.descriptor.DocumentHandler.BARE_DOCUMENT).run()[0]
 
@@ -44,6 +45,7 @@ class TestDescriptorDownloader(unittest.TestCase):
           self.fail("%s has %s %s, but we expected %s" % (auth.nickname, attr, getattr(auth, attr), getattr(stem_auth, attr)))
 
   @require_online
+  @only_run_once
   def test_using_authorities(self):
     """
     Fetches a descriptor from each of the directory authorities. This is
@@ -54,9 +56,6 @@ class TestDescriptorDownloader(unittest.TestCase):
     then this test will need to be updated.
     """
 
-    if test.runner.only_run_once(self):
-      return
-
     queries = []
 
     for nickname, authority in stem.descriptor.remote.get_authorities().items():
@@ -78,27 +77,23 @@ class TestDescriptorDownloader(unittest.TestCase):
       self.assertEqual('moria1', descriptors[0].nickname)
 
   @require_online
+  @only_run_once
   def test_use_directory_mirrors(self):
     """
     Checks that we can fetch and use a list of directory mirrors.
     """
 
-    if test.runner.only_run_once(self):
-      return
-
     downloader = stem.descriptor.remote.DescriptorDownloader()
     downloader.use_directory_mirrors()
     self.assertTrue(len(downloader._endpoints) > 50)
 
   @require_online
+  @only_run_once
   def test_get_server_descriptors(self):
     """
     Exercises the downloader's get_server_descriptors() method.
     """
 
-    if test.runner.only_run_once(self):
-      return
-
     downloader = stem.descriptor.remote.DescriptorDownloader(validate = True)
 
     # Fetch a single descriptor and a batch. I'd love to also exercise
@@ -126,14 +121,12 @@ class TestDescriptorDownloader(unittest.TestCase):
     self.assertEqual(2, len(list(multiple_query)))
 
   @require_online
+  @only_run_once
   def test_get_extrainfo_descriptors(self):
     """
     Exercises the downloader's get_extrainfo_descriptors() method.
     """
 
-    if test.runner.only_run_once(self):
-      return
-
     downloader = stem.descriptor.remote.DescriptorDownloader(validate = True)
 
     single_query = downloader.get_extrainfo_descriptors('9695DFC35FFEB861329B9F1AB04C46397020CE31')
@@ -154,6 +147,7 @@ class TestDescriptorDownloader(unittest.TestCase):
     self.assertEqual(2, len(list(multiple_query)))
 
   @require_online
+  @only_run_once
   def test_get_microdescriptors(self):
     """
     Exercises the downloader's get_microdescriptors() method.
@@ -164,9 +158,6 @@ class TestDescriptorDownloader(unittest.TestCase):
     test.runner.skip(self, '(test presently broken)')
     return
 
-    if test.runner.only_run_once(self):
-      return
-
     downloader = stem.descriptor.remote.DescriptorDownloader(validate = True)
 
     single_query = downloader.get_microdescriptors('6dCl6ab8CLo0LeMjxi/MZgVJiZgWN8WKTesWPBMtyTo')
@@ -187,14 +178,12 @@ class TestDescriptorDownloader(unittest.TestCase):
     self.assertEqual(2, len(list(multiple_query)))
 
   @require_online
+  @only_run_once
   def test_get_consensus(self):
     """
     Exercises the downloader's get_consensus() method.
     """
 
-    if test.runner.only_run_once(self):
-      return
-
     downloader = stem.descriptor.remote.DescriptorDownloader(validate = True)
 
     consensus_query = downloader.get_consensus()
@@ -205,14 +194,12 @@ class TestDescriptorDownloader(unittest.TestCase):
     self.assertTrue(isinstance(consensus[0], stem.descriptor.router_status_entry.RouterStatusEntryV3))
 
   @require_online
+  @only_run_once
   def test_get_key_certificates(self):
     """
     Exercises the downloader's get_key_certificates() method.
     """
 
-    if test.runner.only_run_once(self):
-      return
-
     downloader = stem.descriptor.remote.DescriptorDownloader(validate = True)
 
     single_query = downloader.get_key_certificates('D586D18309DED4CD6D57C18FDB97EFA96D330566')
diff --git a/test/integ/descriptor/server_descriptor.py b/test/integ/descriptor/server_descriptor.py
index 87eba5c..6d5d348 100644
--- a/test/integ/descriptor/server_descriptor.py
+++ b/test/integ/descriptor/server_descriptor.py
@@ -9,8 +9,11 @@ import stem.descriptor
 
 import test.runner
 
+from test.runner import only_run_once
+
 
 class TestServerDescriptor(unittest.TestCase):
+  @only_run_once
   def test_cached_descriptor(self):
     """
     Parses the cached descriptor file in our data directory, checking that it
@@ -18,11 +21,6 @@ class TestServerDescriptor(unittest.TestCase):
     additions.
     """
 
-    # lengthy test and uneffected by targets, so only run once
-
-    if test.runner.only_run_once(self):
-      return
-
     descriptor_path = test.runner.get_runner().get_test_dir('cached-descriptors')
 
     if not os.path.exists(descriptor_path):
diff --git a/test/integ/process.py b/test/integ/process.py
index f611191..639dba5 100644
--- a/test/integ/process.py
+++ b/test/integ/process.py
@@ -24,6 +24,7 @@ import test.runner
 from test.runner import (
   require_controller,
   require_version,
+  only_run_once,
 )
 
 try:
@@ -250,14 +251,12 @@ class TestProcess(unittest.TestCase):
     self.assertTrue('[notice] Configuration file "/path/that/really/shouldnt/exist" not present, using reasonable defaults.' in output)
     self.assertTrue('Configuration was valid' in output)
 
+  @only_run_once
   def test_launch_tor_with_config(self):
     """
     Exercises launch_tor_with_config.
     """
 
-    if test.runner.only_run_once(self):
-      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.
 
@@ -288,14 +287,12 @@ class TestProcess(unittest.TestCase):
       tor_process.kill()
       tor_process.wait()
 
+  @only_run_once
   def test_with_invalid_config(self):
     """
     Spawn a tor process with a configuration that should make it dead on arrival.
     """
 
-    if test.runner.only_run_once(self):
-      return
-
     # Set the same SocksPort and ControlPort, this should fail with...
     #
     #   [warn] Failed to parse/validate config: Failed to bind one of the listener ports.
@@ -314,14 +311,12 @@ class TestProcess(unittest.TestCase):
     except OSError as exc:
       self.assertEqual('Process terminated: Failed to bind one of the listener ports.', str(exc))
 
+  @only_run_once
   def test_launch_tor_with_timeout(self):
     """
     Runs launch_tor where it times out before completing.
     """
 
-    if test.runner.only_run_once(self):
-      return
-
     runner = test.runner.get_runner()
     start_time = time.time()
     config = {'SocksPort': '2777', 'DataDirectory': self.data_directory}
@@ -332,6 +327,7 @@ class TestProcess(unittest.TestCase):
       self.fail('Test should have taken 2-3 seconds, took %i instead' % runtime)
 
   @require_version(stem.version.Requirement.TAKEOWNERSHIP)
+  @only_run_once
   @patch('os.getpid')
   def test_take_ownership_via_pid(self, getpid_mock):
     """
@@ -342,8 +338,6 @@ class TestProcess(unittest.TestCase):
     if not stem.util.system.is_available('sleep'):
       test.runner.skip(self, "('sleep' command is unavailable)")
       return
-    elif test.runner.only_run_once(self):
-      return
 
     sleep_process = subprocess.Popen(['sleep', '60'])
     getpid_mock.return_value = str(sleep_process.pid)
@@ -376,15 +370,13 @@ class TestProcess(unittest.TestCase):
     self.fail("tor didn't quit after the process that owned it terminated")
 
   @require_version(stem.version.Requirement.TAKEOWNERSHIP)
+  @only_run_once
   def test_take_ownership_via_controller(self):
     """
     Checks that the tor process quits after the controller that owns it
     connects, then disconnects..
     """
 
-    if test.runner.only_run_once(self):
-      return
-
     tor_process = stem.process.launch_tor_with_config(
       tor_cmd = test.runner.get_runner().get_tor_command(),
       config = {
diff --git a/test/runner.py b/test/runner.py
index ecf5fb6..0370abd 100644
--- a/test/runner.py
+++ b/test/runner.py
@@ -165,22 +165,21 @@ def require_online(func):
   return wrapped
 
 
-def only_run_once(test_case):
+def only_run_once(func):
   """
   Skips the test if it has ran before. If it hasn't then flags it as being ran.
   This is useful to prevent lengthy tests that are independent of integ targets
   from being run repeatedly with ``RUN_ALL``.
-
-  :param unittest.TestCase test_case: test being ran
-
-  :returns: True if test should be skipped, False otherwise
   """
 
-  if (test_case, test_case.id()) in RAN_TESTS:
-    skip(test_case, '(already ran)')
-    return True
-  else:
-    RAN_TESTS.append((test_case, test_case.id()))
+  def wrapped(self, *args, **kwargs):
+    if (self, self.id()) not in RAN_TESTS:
+      RAN_TESTS.append((self, self.id()))
+      return func(self, *args, **kwargs)
+    else:
+      skip(self, '(already ran)')
+
+  return wrapped
 
 
 def exercise_controller(test_case, controller):





More information about the tor-commits mailing list