]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/commitdiff
move testutil into test/common_util.py, since it doesn't count as 'code under test...
authorBrian Warner <warner@allmydata.com>
Wed, 29 Oct 2008 04:28:31 +0000 (21:28 -0700)
committerBrian Warner <warner@allmydata.com>
Wed, 29 Oct 2008 04:28:31 +0000 (21:28 -0700)
15 files changed:
src/allmydata/test/common.py
src/allmydata/test/common_util.py [new file with mode: 0644]
src/allmydata/test/test_client.py
src/allmydata/test/test_dirnode.py
src/allmydata/test/test_encode.py
src/allmydata/test/test_immutable_checker.py
src/allmydata/test/test_introducer.py
src/allmydata/test/test_iputil.py
src/allmydata/test/test_mutable.py
src/allmydata/test/test_node.py
src/allmydata/test/test_stats.py
src/allmydata/test/test_upload.py
src/allmydata/test/test_util.py
src/allmydata/test/test_web.py
src/allmydata/util/testutil.py [deleted file]

index 3fd6b6a3f7c6d4eeb152da38b8971ae341f195bb..af86e77a64e2a7ad3749976ed433bd534c1862b2 100644 (file)
@@ -16,9 +16,10 @@ from allmydata.checker_results import CheckerResults, CheckAndRepairResults, \
      DeepCheckResults, DeepCheckAndRepairResults
 from allmydata.mutable.common import CorruptShareError
 from allmydata.storage import storage_index_to_dir
      DeepCheckResults, DeepCheckAndRepairResults
 from allmydata.mutable.common import CorruptShareError
 from allmydata.storage import storage_index_to_dir
-from allmydata.util import log, testutil, fileutil, pollmixin
+from allmydata.util import log, fileutil, pollmixin
 from allmydata.stats import PickleStatsGatherer
 from allmydata.key_generator import KeyGeneratorService
 from allmydata.stats import PickleStatsGatherer
 from allmydata.key_generator import KeyGeneratorService
+import common_util as testutil
 
 
 def flush_but_dont_ignore(res):
 
 
 def flush_but_dont_ignore(res):
diff --git a/src/allmydata/test/common_util.py b/src/allmydata/test/common_util.py
new file mode 100644 (file)
index 0000000..27d6b43
--- /dev/null
@@ -0,0 +1,151 @@
+import os, signal, time
+from random import randrange
+
+from twisted.internet import reactor, defer
+from twisted.python import failure
+
+def insecurerandstr(n):
+    return ''.join(map(chr, map(randrange, [0]*n, [256]*n)))
+
+def flip_bit(good, which):
+    # flip the low-order bit of good[which]
+    if which == -1:
+        pieces = good[:which], good[-1:], ""
+    else:
+        pieces = good[:which], good[which:which+1], good[which+1:]
+    return pieces[0] + chr(ord(pieces[1]) ^ 0x01) + pieces[2]
+
+def flip_one_bit(s, offset=0, size=None):
+    """ flip one random bit of the string s, in a byte greater than or equal to offset and less
+    than offset+size. """
+    if size is None:
+        size=len(s)-offset
+    i = randrange(offset, offset+size)
+    result = s[:i] + chr(ord(s[i])^(0x01<<randrange(0, 8))) + s[i+1:]
+    assert result != s, "Internal error -- flip_one_bit() produced the same string as its input: %s == %s" % (result, s)
+    return result
+
+class SignalMixin:
+    # This class is necessary for any code which wants to use Processes
+    # outside the usual reactor.run() environment. It is copied from
+    # Twisted's twisted.test.test_process
+    sigchldHandler = None
+
+    def setUpClass(self):
+        # make sure SIGCHLD handler is installed, as it should be on
+        # reactor.run(). problem is reactor may not have been run when this
+        # test runs.
+        if hasattr(reactor, "_handleSigchld") and hasattr(signal, "SIGCHLD"):
+            self.sigchldHandler = signal.signal(signal.SIGCHLD,
+                                                reactor._handleSigchld)
+
+    def tearDownClass(self):
+        if self.sigchldHandler:
+            signal.signal(signal.SIGCHLD, self.sigchldHandler)
+
+class StallMixin:
+    def stall(self, res=None, delay=1):
+        d = defer.Deferred()
+        reactor.callLater(delay, d.callback, res)
+        return d
+
+class ShouldFailMixin:
+
+    def shouldFail(self, expected_failure, which, substring,
+                   callable, *args, **kwargs):
+        assert substring is None or isinstance(substring, str)
+        d = defer.maybeDeferred(callable, *args, **kwargs)
+        def done(res):
+            if isinstance(res, failure.Failure):
+                res.trap(expected_failure)
+                if substring:
+                    self.failUnless(substring in str(res),
+                                    "%s: substring '%s' not in '%s'"
+                                    % (which, substring, str(res)))
+                # return the Failure for further analysis, but in a form that
+                # doesn't make the Deferred chain think that we failed.
+                return [res]
+            else:
+                self.fail("%s was supposed to raise %s, not get '%s'" %
+                          (which, expected_failure, res))
+        d.addBoth(done)
+        return d
+
+
+class TestMixin(SignalMixin):
+    def setUp(self, repeatable=False):
+        """
+        @param repeatable: install the repeatable_randomness hacks to attempt
+            to without access to real randomness and real time.time from the
+            code under test
+        """
+        self.repeatable = repeatable
+        if self.repeatable:
+            import repeatable_random
+            repeatable_random.force_repeatability()
+        if hasattr(time, 'realtime'):
+            self.teststarttime = time.realtime()
+        else:
+            self.teststarttime = time.time()
+
+    def tearDown(self):
+        if self.repeatable:
+            import repeatable_random
+            repeatable_random.restore_non_repeatability()
+        self.clean_pending(required_to_quiesce=True)
+
+    def clean_pending(self, dummy=None, required_to_quiesce=True):
+        """
+        This handy method cleans all pending tasks from the reactor.
+
+        When writing a unit test, consider the following question:
+
+            Is the code that you are testing required to release control once it
+            has done its job, so that it is impossible for it to later come around
+            (with a delayed reactor task) and do anything further?
+
+        If so, then trial will usefully test that for you -- if the code under
+        test leaves any pending tasks on the reactor then trial will fail it.
+
+        On the other hand, some code is *not* required to release control -- some
+        code is allowed to continuously maintain control by rescheduling reactor
+        tasks in order to do ongoing work.  Trial will incorrectly require that
+        code to clean up all its tasks from the reactor.
+
+        Most people think that such code should be amended to have an optional
+        "shutdown" operation that releases all control, but on the contrary it is
+        good design for some code to *not* have a shutdown operation, but instead
+        to have a "crash-only" design in which it recovers from crash on startup.
+
+        If the code under test is of the "long-running" kind, which is *not*
+        required to shutdown cleanly in order to pass tests, then you can simply
+        call testutil.clean_pending() at the end of the unit test, and trial will
+        be satisfied.
+        """
+        pending = reactor.getDelayedCalls()
+        active = bool(pending)
+        for p in pending:
+            if p.active():
+                p.cancel()
+            else:
+                print "WEIRNESS! pending timed call not active+!"
+        if required_to_quiesce and active:
+            self.fail("Reactor was still active when it was required to be quiescent.")
+
+try:
+    import win32file
+    import win32con
+    def make_readonly(path):
+        win32file.SetFileAttributes(path, win32con.FILE_ATTRIBUTE_READONLY)
+    def make_accessible(path):
+        win32file.SetFileAttributes(path, win32con.FILE_ATTRIBUTE_NORMAL)
+except ImportError:
+    import stat
+    def _make_readonly(path):
+        os.chmod(path, stat.S_IREAD)
+        os.chmod(os.path.dirname(path), stat.S_IREAD)
+    def _make_accessible(path):
+        os.chmod(os.path.dirname(path), stat.S_IWRITE | stat.S_IEXEC | stat.S_IREAD)
+        os.chmod(path, stat.S_IWRITE | stat.S_IEXEC | stat.S_IREAD)
+    make_readonly = _make_readonly
+    make_accessible = _make_accessible
index 3d0a9085ab3839efa171de6a6fa19b8435230f1c..48db3b050dbc9ee1c797bd2e28fd08b66f84991a 100644 (file)
@@ -7,8 +7,9 @@ from twisted.python import log
 import allmydata
 from allmydata import client
 from allmydata.introducer.client import IntroducerClient
 import allmydata
 from allmydata import client
 from allmydata.introducer.client import IntroducerClient
-from allmydata.util import base32, testutil
+from allmydata.util import base32
 from foolscap.eventual import flushEventualQueue
 from foolscap.eventual import flushEventualQueue
+import common_util as testutil
 
 class FakeIntroducerClient(IntroducerClient):
     def __init__(self):
 
 class FakeIntroducerClient(IntroducerClient):
     def __init__(self):
index 9fa9fd28216d06314e69a4d6263cfbf25268d80e..e656bad28f1078b9472308747f56dedd55594e31 100644 (file)
@@ -9,11 +9,12 @@ from allmydata.interfaces import IURI, IClient, IMutableFileNode, \
      INewDirectoryURI, IReadonlyNewDirectoryURI, IFileNode, \
      ExistingChildError, NoSuchChildError, \
      IDeepCheckResults, IDeepCheckAndRepairResults
      INewDirectoryURI, IReadonlyNewDirectoryURI, IFileNode, \
      ExistingChildError, NoSuchChildError, \
      IDeepCheckResults, IDeepCheckAndRepairResults
-from allmydata.util import hashutil, testutil
+from allmydata.util import hashutil
 from allmydata.monitor import Monitor
 from allmydata.test.common import make_chk_file_uri, make_mutable_file_uri, \
      FakeDirectoryNode, create_chk_filenode
 from allmydata.checker_results import CheckerResults, CheckAndRepairResults
 from allmydata.monitor import Monitor
 from allmydata.test.common import make_chk_file_uri, make_mutable_file_uri, \
      FakeDirectoryNode, create_chk_filenode
 from allmydata.checker_results import CheckerResults, CheckAndRepairResults
+import common_util as testutil
 
 # to test dirnode.py, we want to construct a tree of real DirectoryNodes that
 # contain pointers to fake files. We start with a fake MutableFileNode that
 
 # to test dirnode.py, we want to construct a tree of real DirectoryNodes that
 # contain pointers to fake files. We start with a fake MutableFileNode that
index 0a477bbbbcd2bb217bf9ba1f5947542c8669a372..190b4c52bbedab57b33ac55c4dae4f92da6ee075 100644 (file)
@@ -7,9 +7,10 @@ from twisted.python.failure import Failure
 from foolscap import eventual
 from allmydata import hashtree, uri
 from allmydata.immutable import encode, upload, download
 from foolscap import eventual
 from allmydata import hashtree, uri
 from allmydata.immutable import encode, upload, download
-from allmydata.util import hashutil, testutil
+from allmydata.util import hashutil
 from allmydata.util.assertutil import _assert
 from allmydata.interfaces import IStorageBucketWriter, IStorageBucketReader, NotEnoughSharesError
 from allmydata.util.assertutil import _assert
 from allmydata.interfaces import IStorageBucketWriter, IStorageBucketReader, NotEnoughSharesError
+import common_util as testutil
 
 class LostPeerError(Exception):
     pass
 
 class LostPeerError(Exception):
     pass
index 8bf28f15410c75c3459f8f7e1752d17515c3106e..e743726b698a75714cff06717ef51c15d06dbb34 100644 (file)
@@ -1,11 +1,11 @@
 from allmydata.immutable import upload
 from allmydata.test.common import SystemTestMixin, ShareManglingMixin
 from allmydata.immutable import upload
 from allmydata.test.common import SystemTestMixin, ShareManglingMixin
-from allmydata.util import testutil
 from allmydata.monitor import Monitor
 from allmydata.interfaces import IURI, NotEnoughSharesError
 from twisted.internet import defer
 from twisted.trial import unittest
 import random, struct
 from allmydata.monitor import Monitor
 from allmydata.interfaces import IURI, NotEnoughSharesError
 from twisted.internet import defer
 from twisted.trial import unittest
 import random, struct
+import common_util as testutil
 
 TEST_DATA="\x02"*(upload.Uploader.URI_LIT_SIZE_THRESHOLD+1)
 
 
 TEST_DATA="\x02"*(upload.Uploader.URI_LIT_SIZE_THRESHOLD+1)
 
index 96a587a712df9b5630c4fd95773d7d42d4e65cb0..104e0cbd5a35cfbd0c10e0e94d97494538fe0ec7 100644 (file)
@@ -14,7 +14,8 @@ from allmydata.introducer.server import IntroducerService
 # test compatibility with old introducer .tac files
 from allmydata.introducer import IntroducerNode
 from allmydata.introducer import old
 # test compatibility with old introducer .tac files
 from allmydata.introducer import IntroducerNode
 from allmydata.introducer import old
-from allmydata.util import testutil, idlib, pollmixin
+from allmydata.util import idlib, pollmixin
+import common_util as testutil
 
 class FakeNode(Referenceable):
     pass
 
 class FakeNode(Referenceable):
     pass
index 0f16f72c31559aef9069b64593f51f5ee3799ff9..21550893044c67f4357037d89f32d2c2fc6b34b3 100644 (file)
@@ -1,8 +1,8 @@
 
 
-from allmydata.util import iputil, testutil
-
-from twisted.trial import unittest
 import re
 import re
+from twisted.trial import unittest
+from allmydata.util import iputil
+import common_util as testutil
 
 DOTTED_QUAD_RE=re.compile("^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$")
 
 
 DOTTED_QUAD_RE=re.compile("^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$")
 
index d778b93ad1f5db1909ed18404a25241d62b08bb2..63983de59d7d5a5eb1ff6ea11d2a614b12c1a7d9 100644 (file)
@@ -6,7 +6,7 @@ from twisted.internet import defer, reactor
 from twisted.python import failure
 from allmydata import uri, storage
 from allmydata.immutable import download
 from twisted.python import failure
 from allmydata import uri, storage
 from allmydata.immutable import download
-from allmydata.util import base32, testutil, idlib
+from allmydata.util import base32, idlib
 from allmydata.util.idlib import shortnodeid_b2a
 from allmydata.util.hashutil import tagged_hash
 from allmydata.util.fileutil import make_dirs
 from allmydata.util.idlib import shortnodeid_b2a
 from allmydata.util.hashutil import tagged_hash
 from allmydata.util.fileutil import make_dirs
@@ -29,6 +29,8 @@ from allmydata.mutable.servermap import ServerMap, ServermapUpdater
 from allmydata.mutable.layout import unpack_header, unpack_share
 from allmydata.mutable.repair import MustForceRepairError
 
 from allmydata.mutable.layout import unpack_header, unpack_share
 from allmydata.mutable.repair import MustForceRepairError
 
+import common_util as testutil
+
 # this "FastMutableFileNode" exists solely to speed up tests by using smaller
 # public/private keys. Once we switch to fast DSA-based keys, we can get rid
 # of this.
 # this "FastMutableFileNode" exists solely to speed up tests by using smaller
 # public/private keys. Once we switch to fast DSA-based keys, we can get rid
 # of this.
index fad0e15f7f5ce04ae06be60ed582be8266250934..391883eb0f54e5915bd7cff1f0310f5ec70e2e52 100644 (file)
@@ -7,7 +7,8 @@ from twisted.python import log
 from foolscap.eventual import flushEventualQueue
 from twisted.application import service
 from allmydata.node import Node, formatTimeTahoeStyle
 from foolscap.eventual import flushEventualQueue
 from twisted.application import service
 from allmydata.node import Node, formatTimeTahoeStyle
-from allmydata.util import testutil, fileutil
+from allmydata.util import fileutil
+import common_util as testutil
 
 class LoggingMultiService(service.MultiService):
     def log(self, msg, **kw):
 
 class LoggingMultiService(service.MultiService):
     def log(self, msg, **kw):
index 4cf4d8a55968feca5cc1fbdd90bd21142119bfae..c2ff496b57438dd0d4d5f6a334b3e968f57ebb30 100644 (file)
@@ -2,7 +2,8 @@
 from twisted.trial import unittest
 from twisted.application import service
 from allmydata.stats import CPUUsageMonitor
 from twisted.trial import unittest
 from twisted.application import service
 from allmydata.stats import CPUUsageMonitor
-from allmydata.util import testutil, pollmixin
+from allmydata.util import pollmixin
+import common_util as testutil
 
 class FasterMonitor(CPUUsageMonitor):
     POLL_INTERVAL = 0.1
 
 class FasterMonitor(CPUUsageMonitor):
     POLL_INTERVAL = 0.1
index 6bfe12ebe9be75cb277bcf43ec1eb443f674e1bc..475051a807dbfd909fb89202cbc4a1d7518fed58 100644 (file)
@@ -1,18 +1,18 @@
 
 import os
 
 import os
+from cStringIO import StringIO
 from twisted.trial import unittest
 from twisted.python.failure import Failure
 from twisted.python import log
 from twisted.internet import defer
 from twisted.trial import unittest
 from twisted.python.failure import Failure
 from twisted.python import log
 from twisted.internet import defer
-from cStringIO import StringIO
+from foolscap import eventual
 
 from allmydata import uri
 from allmydata.immutable import upload
 from allmydata.interfaces import IFileURI, FileTooLargeError, NotEnoughSharesError
 from allmydata.util.assertutil import precondition
 from allmydata.util.deferredutil import DeferredListShouldSucceed
 
 from allmydata import uri
 from allmydata.immutable import upload
 from allmydata.interfaces import IFileURI, FileTooLargeError, NotEnoughSharesError
 from allmydata.util.assertutil import precondition
 from allmydata.util.deferredutil import DeferredListShouldSucceed
-from allmydata.util.testutil import ShouldFailMixin
-from foolscap import eventual
+from common_util import ShouldFailMixin
 
 MiB = 1024*1024
 
 
 MiB = 1024*1024
 
index 5414d9b5de5508477ba1b97b763bc40e614f1af3..1dbce56bcd1b74502c6ca319f1d9218c3b025271 100644 (file)
@@ -7,7 +7,7 @@ from twisted.internet import defer, reactor
 from twisted.python import failure
 
 from allmydata.util import base32, idlib, humanreadable, mathutil, hashutil
 from twisted.python import failure
 
 from allmydata.util import base32, idlib, humanreadable, mathutil, hashutil
-from allmydata.util import assertutil, fileutil, testutil, deferredutil
+from allmydata.util import assertutil, fileutil, deferredutil
 from allmydata.util import limiter, time_format, pollmixin
 
 class Base32(unittest.TestCase):
 from allmydata.util import limiter, time_format, pollmixin
 
 class Base32(unittest.TestCase):
index b41380e7f74e1e4a990aab947cc042071e269a10..754fee3e2a62fcf020c0b28d55b26a2f08ef9bc4 100644 (file)
@@ -8,12 +8,13 @@ from twisted.python import failure, log
 from allmydata import interfaces, provisioning, uri, webish
 from allmydata.immutable import upload, download
 from allmydata.web import status, common
 from allmydata import interfaces, provisioning, uri, webish
 from allmydata.immutable import upload, download
 from allmydata.web import status, common
-from allmydata.util import fileutil, testutil, base32
+from allmydata.util import fileutil, base32
 from allmydata.test.common import FakeDirectoryNode, FakeCHKFileNode, \
      FakeMutableFileNode, create_chk_filenode
 from allmydata.interfaces import IURI, INewDirectoryURI, \
      IReadonlyNewDirectoryURI, IFileURI, IMutableFileURI, IMutableFileNode
 from allmydata.mutable import servermap, publish, retrieve
 from allmydata.test.common import FakeDirectoryNode, FakeCHKFileNode, \
      FakeMutableFileNode, create_chk_filenode
 from allmydata.interfaces import IURI, INewDirectoryURI, \
      IReadonlyNewDirectoryURI, IFileURI, IMutableFileURI, IMutableFileNode
 from allmydata.mutable import servermap, publish, retrieve
+import common_util as testutil
 
 # create a fake uploader/downloader, and a couple of fake dirnodes, then
 # create a webserver that works against them
 
 # create a fake uploader/downloader, and a couple of fake dirnodes, then
 # create a webserver that works against them
diff --git a/src/allmydata/util/testutil.py b/src/allmydata/util/testutil.py
deleted file mode 100644 (file)
index 27d6b43..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-import os, signal, time
-from random import randrange
-
-from twisted.internet import reactor, defer
-from twisted.python import failure
-
-def insecurerandstr(n):
-    return ''.join(map(chr, map(randrange, [0]*n, [256]*n)))
-
-def flip_bit(good, which):
-    # flip the low-order bit of good[which]
-    if which == -1:
-        pieces = good[:which], good[-1:], ""
-    else:
-        pieces = good[:which], good[which:which+1], good[which+1:]
-    return pieces[0] + chr(ord(pieces[1]) ^ 0x01) + pieces[2]
-
-def flip_one_bit(s, offset=0, size=None):
-    """ flip one random bit of the string s, in a byte greater than or equal to offset and less
-    than offset+size. """
-    if size is None:
-        size=len(s)-offset
-    i = randrange(offset, offset+size)
-    result = s[:i] + chr(ord(s[i])^(0x01<<randrange(0, 8))) + s[i+1:]
-    assert result != s, "Internal error -- flip_one_bit() produced the same string as its input: %s == %s" % (result, s)
-    return result
-
-class SignalMixin:
-    # This class is necessary for any code which wants to use Processes
-    # outside the usual reactor.run() environment. It is copied from
-    # Twisted's twisted.test.test_process
-    sigchldHandler = None
-
-    def setUpClass(self):
-        # make sure SIGCHLD handler is installed, as it should be on
-        # reactor.run(). problem is reactor may not have been run when this
-        # test runs.
-        if hasattr(reactor, "_handleSigchld") and hasattr(signal, "SIGCHLD"):
-            self.sigchldHandler = signal.signal(signal.SIGCHLD,
-                                                reactor._handleSigchld)
-
-    def tearDownClass(self):
-        if self.sigchldHandler:
-            signal.signal(signal.SIGCHLD, self.sigchldHandler)
-
-class StallMixin:
-    def stall(self, res=None, delay=1):
-        d = defer.Deferred()
-        reactor.callLater(delay, d.callback, res)
-        return d
-
-class ShouldFailMixin:
-
-    def shouldFail(self, expected_failure, which, substring,
-                   callable, *args, **kwargs):
-        assert substring is None or isinstance(substring, str)
-        d = defer.maybeDeferred(callable, *args, **kwargs)
-        def done(res):
-            if isinstance(res, failure.Failure):
-                res.trap(expected_failure)
-                if substring:
-                    self.failUnless(substring in str(res),
-                                    "%s: substring '%s' not in '%s'"
-                                    % (which, substring, str(res)))
-                # return the Failure for further analysis, but in a form that
-                # doesn't make the Deferred chain think that we failed.
-                return [res]
-            else:
-                self.fail("%s was supposed to raise %s, not get '%s'" %
-                          (which, expected_failure, res))
-        d.addBoth(done)
-        return d
-
-
-class TestMixin(SignalMixin):
-    def setUp(self, repeatable=False):
-        """
-        @param repeatable: install the repeatable_randomness hacks to attempt
-            to without access to real randomness and real time.time from the
-            code under test
-        """
-        self.repeatable = repeatable
-        if self.repeatable:
-            import repeatable_random
-            repeatable_random.force_repeatability()
-        if hasattr(time, 'realtime'):
-            self.teststarttime = time.realtime()
-        else:
-            self.teststarttime = time.time()
-
-    def tearDown(self):
-        if self.repeatable:
-            import repeatable_random
-            repeatable_random.restore_non_repeatability()
-        self.clean_pending(required_to_quiesce=True)
-
-    def clean_pending(self, dummy=None, required_to_quiesce=True):
-        """
-        This handy method cleans all pending tasks from the reactor.
-
-        When writing a unit test, consider the following question:
-
-            Is the code that you are testing required to release control once it
-            has done its job, so that it is impossible for it to later come around
-            (with a delayed reactor task) and do anything further?
-
-        If so, then trial will usefully test that for you -- if the code under
-        test leaves any pending tasks on the reactor then trial will fail it.
-
-        On the other hand, some code is *not* required to release control -- some
-        code is allowed to continuously maintain control by rescheduling reactor
-        tasks in order to do ongoing work.  Trial will incorrectly require that
-        code to clean up all its tasks from the reactor.
-
-        Most people think that such code should be amended to have an optional
-        "shutdown" operation that releases all control, but on the contrary it is
-        good design for some code to *not* have a shutdown operation, but instead
-        to have a "crash-only" design in which it recovers from crash on startup.
-
-        If the code under test is of the "long-running" kind, which is *not*
-        required to shutdown cleanly in order to pass tests, then you can simply
-        call testutil.clean_pending() at the end of the unit test, and trial will
-        be satisfied.
-        """
-        pending = reactor.getDelayedCalls()
-        active = bool(pending)
-        for p in pending:
-            if p.active():
-                p.cancel()
-            else:
-                print "WEIRNESS! pending timed call not active+!"
-        if required_to_quiesce and active:
-            self.fail("Reactor was still active when it was required to be quiescent.")
-
-try:
-    import win32file
-    import win32con
-    def make_readonly(path):
-        win32file.SetFileAttributes(path, win32con.FILE_ATTRIBUTE_READONLY)
-    def make_accessible(path):
-        win32file.SetFileAttributes(path, win32con.FILE_ATTRIBUTE_NORMAL)
-except ImportError:
-    import stat
-    def _make_readonly(path):
-        os.chmod(path, stat.S_IREAD)
-        os.chmod(os.path.dirname(path), stat.S_IREAD)
-    def _make_accessible(path):
-        os.chmod(os.path.dirname(path), stat.S_IWRITE | stat.S_IEXEC | stat.S_IREAD)
-        os.chmod(path, stat.S_IWRITE | stat.S_IEXEC | stat.S_IREAD)
-    make_readonly = _make_readonly
-    make_accessible = _make_accessible