From 294e3fb6826b29f90d03d4bcf6a59c32846f8677 Mon Sep 17 00:00:00 2001
From: Brian Warner <warner@allmydata.com>
Date: Tue, 28 Oct 2008 21:15:48 -0700
Subject: [PATCH] util: move PollMixin to a separate file (pollmixin.py), so
 testutil can be moved into test/

---
 src/allmydata/client.py               |  4 +--
 src/allmydata/test/check_memory.py    |  4 +--
 src/allmydata/test/common.py          |  4 +--
 src/allmydata/test/test_introducer.py |  6 ++---
 src/allmydata/test/test_keygen.py     |  4 +--
 src/allmydata/test/test_runner.py     |  4 +--
 src/allmydata/test/test_stats.py      |  4 +--
 src/allmydata/test/test_util.py       |  6 ++---
 src/allmydata/util/pollmixin.py       | 36 +++++++++++++++++++++++++++
 src/allmydata/util/testutil.py        | 34 +------------------------
 10 files changed, 55 insertions(+), 51 deletions(-)
 create mode 100644 src/allmydata/util/pollmixin.py

diff --git a/src/allmydata/client.py b/src/allmydata/client.py
index 797d1745..463a5cbd 100644
--- a/src/allmydata/client.py
+++ b/src/allmydata/client.py
@@ -18,7 +18,7 @@ from allmydata.immutable.filenode import FileNode, LiteralFileNode
 from allmydata.offloaded import Helper
 from allmydata.control import ControlServer
 from allmydata.introducer.client import IntroducerClient
-from allmydata.util import hashutil, base32, testutil, fileutil
+from allmydata.util import hashutil, base32, pollmixin, fileutil
 from allmydata.uri import LiteralFileURI
 from allmydata.dirnode import NewDirectoryNode
 from allmydata.mutable.node import MutableFileNode, MutableWatcher
@@ -38,7 +38,7 @@ class StubClient(Referenceable):
 def _make_secret():
     return base32.b2a(os.urandom(hashutil.CRYPTO_VAL_SIZE)) + "\n"
 
-class Client(node.Node, testutil.PollMixin):
+class Client(node.Node, pollmixin.PollMixin):
     implements(IStatsProducer)
 
     PORTNUMFILE = "client.port"
diff --git a/src/allmydata/test/check_memory.py b/src/allmydata/test/check_memory.py
index ddfa4337..a106e6b1 100644
--- a/src/allmydata/test/check_memory.py
+++ b/src/allmydata/test/check_memory.py
@@ -8,7 +8,7 @@ from twisted.web import client as tw_client
 from allmydata import client, introducer
 from allmydata.immutable import upload
 from allmydata.scripts import create_node
-from allmydata.util import testutil, fileutil
+from allmydata.util import fileutil, pollmixin
 import foolscap
 from foolscap import eventual
 from twisted.python import log
@@ -57,7 +57,7 @@ def discardPage(url, stall=False, *args, **kwargs):
     reactor.connectTCP(host, port, factory)
     return factory.deferred
 
-class SystemFramework(testutil.PollMixin):
+class SystemFramework(pollmixin.PollMixin):
     numnodes = 5
 
     def __init__(self, basedir, mode):
diff --git a/src/allmydata/test/common.py b/src/allmydata/test/common.py
index d09ebff2..3fd6b6a3 100644
--- a/src/allmydata/test/common.py
+++ b/src/allmydata/test/common.py
@@ -16,7 +16,7 @@ from allmydata.checker_results import CheckerResults, CheckAndRepairResults, \
      DeepCheckResults, DeepCheckAndRepairResults
 from allmydata.mutable.common import CorruptShareError
 from allmydata.storage import storage_index_to_dir
-from allmydata.util import log, testutil, fileutil
+from allmydata.util import log, testutil, fileutil, pollmixin
 from allmydata.stats import PickleStatsGatherer
 from allmydata.key_generator import KeyGeneratorService
 
@@ -291,7 +291,7 @@ class LoggingServiceParent(service.MultiService):
         return log.msg(*args, **kwargs)
 
 
-class SystemTestMixin(testutil.PollMixin, testutil.StallMixin):
+class SystemTestMixin(pollmixin.PollMixin, testutil.StallMixin):
 
     def setUp(self):
         self.sparent = service.MultiService()
diff --git a/src/allmydata/test/test_introducer.py b/src/allmydata/test/test_introducer.py
index 08d52915..96a587a7 100644
--- a/src/allmydata/test/test_introducer.py
+++ b/src/allmydata/test/test_introducer.py
@@ -14,7 +14,7 @@ from allmydata.introducer.server import IntroducerService
 # test compatibility with old introducer .tac files
 from allmydata.introducer import IntroducerNode
 from allmydata.introducer import old
-from allmydata.util import testutil, idlib
+from allmydata.util import testutil, idlib, pollmixin
 
 class FakeNode(Referenceable):
     pass
@@ -46,7 +46,7 @@ class ServiceMixin:
         d.addCallback(flushEventualQueue)
         return d
 
-class Introducer(ServiceMixin, unittest.TestCase, testutil.PollMixin):
+class Introducer(ServiceMixin, unittest.TestCase, pollmixin.PollMixin):
 
     def test_create(self):
         ic = IntroducerClient(None, "introducer.furl", "my_nickname",
@@ -75,7 +75,7 @@ class Introducer(ServiceMixin, unittest.TestCase, testutil.PollMixin):
         self.failUnlessEqual(len(i.get_announcements()), 2)
         self.failUnlessEqual(len(i.get_subscribers()), 0)
 
-class SystemTestMixin(ServiceMixin, testutil.PollMixin):
+class SystemTestMixin(ServiceMixin, pollmixin.PollMixin):
 
     def setUp(self):
         ServiceMixin.setUp(self)
diff --git a/src/allmydata/test/test_keygen.py b/src/allmydata/test/test_keygen.py
index 27ed94db..11b8f7de 100644
--- a/src/allmydata/test/test_keygen.py
+++ b/src/allmydata/test/test_keygen.py
@@ -6,7 +6,7 @@ from twisted.application import service
 from foolscap import Tub, eventual
 
 from allmydata import key_generator
-from allmydata.util import testutil
+from allmydata.util import pollmixin
 from pycryptopp.publickey import rsa
 
 def flush_but_dont_ignore(res):
@@ -16,7 +16,7 @@ def flush_but_dont_ignore(res):
     d.addCallback(_done)
     return d
 
-class KeyGenService(unittest.TestCase, testutil.PollMixin):
+class KeyGenService(unittest.TestCase, pollmixin.PollMixin):
     def setUp(self):
         self.parent = service.MultiService()
         self.parent.startService()
diff --git a/src/allmydata/test/test_runner.py b/src/allmydata/test/test_runner.py
index c34d2e25..426163c0 100644
--- a/src/allmydata/test/test_runner.py
+++ b/src/allmydata/test/test_runner.py
@@ -6,7 +6,7 @@ from twisted.python import usage, runtime
 from twisted.internet import defer
 import os.path, re
 from allmydata.scripts import runner
-from allmydata.util import fileutil, testutil
+from allmydata.util import fileutil, pollmixin
 
 class CreateNode(unittest.TestCase):
     def workdir(self, name):
@@ -93,7 +93,7 @@ class CreateNode(unittest.TestCase):
                               [],
                               run_by_human=False)
 
-class RunNode(unittest.TestCase, testutil.PollMixin):
+class RunNode(unittest.TestCase, pollmixin.PollMixin):
     def workdir(self, name):
         basedir = os.path.join("test_runner", "RunNode", name)
         fileutil.make_dirs(basedir)
diff --git a/src/allmydata/test/test_stats.py b/src/allmydata/test/test_stats.py
index 26286693..4cf4d8a5 100644
--- a/src/allmydata/test/test_stats.py
+++ b/src/allmydata/test/test_stats.py
@@ -2,13 +2,13 @@
 from twisted.trial import unittest
 from twisted.application import service
 from allmydata.stats import CPUUsageMonitor
-from allmydata.util import testutil
+from allmydata.util import testutil, pollmixin
 
 class FasterMonitor(CPUUsageMonitor):
     POLL_INTERVAL = 0.1
 
 
-class CPUUsage(unittest.TestCase, testutil.PollMixin, testutil.StallMixin):
+class CPUUsage(unittest.TestCase, pollmixin.PollMixin, testutil.StallMixin):
     def setUp(self):
         self.s = service.MultiService()
         self.s.startService()
diff --git a/src/allmydata/test/test_util.py b/src/allmydata/test/test_util.py
index babaef78..5414d9b5 100644
--- a/src/allmydata/test/test_util.py
+++ b/src/allmydata/test/test_util.py
@@ -8,7 +8,7 @@ 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 limiter, time_format
+from allmydata.util import limiter, time_format, pollmixin
 
 class Base32(unittest.TestCase):
     def test_b2a_matches_Pythons(self):
@@ -330,7 +330,7 @@ class FileUtil(unittest.TestCase):
 
 class PollMixinTests(unittest.TestCase):
     def setUp(self):
-        self.pm = testutil.PollMixin()
+        self.pm = pollmixin.PollMixin()
 
     def test_PollMixin_True(self):
         d = self.pm.poll(check_f=lambda : True,
@@ -350,7 +350,7 @@ class PollMixinTests(unittest.TestCase):
         def _suc(res):
             self.fail("poll should have failed, not returned %s" % (res,))
         def _err(f):
-            f.trap(testutil.TimeoutError)
+            f.trap(pollmixin.TimeoutError)
             return None # success
         d.addCallbacks(_suc, _err)
         return d
diff --git a/src/allmydata/util/pollmixin.py b/src/allmydata/util/pollmixin.py
new file mode 100644
index 00000000..4f7ab828
--- /dev/null
+++ b/src/allmydata/util/pollmixin.py
@@ -0,0 +1,36 @@
+
+import time
+from twisted.internet import task
+
+class TimeoutError(Exception):
+    pass
+
+class PollComplete(Exception):
+    pass
+
+class PollMixin:
+
+    def poll(self, check_f, pollinterval=0.01, timeout=100):
+        # Return a Deferred, then call check_f periodically until it returns
+        # True, at which point the Deferred will fire.. If check_f raises an
+        # exception, the Deferred will errback. If the check_f does not
+        # indicate success within timeout= seconds, the Deferred will
+        # errback. If timeout=None, no timeout will be enforced, and the loop
+        # will poll forever (or really until Trial times out).
+        cutoff = None
+        if timeout is not None:
+            cutoff = time.time() + timeout
+        lc = task.LoopingCall(self._poll, check_f, cutoff)
+        d = lc.start(pollinterval)
+        def _convert_done(f):
+            f.trap(PollComplete)
+            return None
+        d.addErrback(_convert_done)
+        return d
+
+    def _poll(self, check_f, cutoff):
+        if cutoff is not None and time.time() > cutoff:
+            raise TimeoutError("PollMixin never saw %s return True" % check_f)
+        if check_f():
+            raise PollComplete()
+
diff --git a/src/allmydata/util/testutil.py b/src/allmydata/util/testutil.py
index 84911306..27d6b434 100644
--- a/src/allmydata/util/testutil.py
+++ b/src/allmydata/util/testutil.py
@@ -1,7 +1,7 @@
 import os, signal, time
 from random import randrange
 
-from twisted.internet import reactor, defer, task
+from twisted.internet import reactor, defer
 from twisted.python import failure
 
 def insecurerandstr(n):
@@ -43,38 +43,6 @@ class SignalMixin:
         if self.sigchldHandler:
             signal.signal(signal.SIGCHLD, self.sigchldHandler)
 
-class TimeoutError(Exception):
-    pass
-
-class PollComplete(Exception):
-    pass
-
-class PollMixin:
-
-    def poll(self, check_f, pollinterval=0.01, timeout=100):
-        # Return a Deferred, then call check_f periodically until it returns
-        # True, at which point the Deferred will fire.. If check_f raises an
-        # exception, the Deferred will errback. If the check_f does not
-        # indicate success within timeout= seconds, the Deferred will
-        # errback. If timeout=None, no timeout will be enforced, and the loop
-        # will poll forever (or really until Trial times out).
-        cutoff = None
-        if timeout is not None:
-            cutoff = time.time() + timeout
-        lc = task.LoopingCall(self._poll, check_f, cutoff)
-        d = lc.start(pollinterval)
-        def _convert_done(f):
-            f.trap(PollComplete)
-            return None
-        d.addErrback(_convert_done)
-        return d
-
-    def _poll(self, check_f, cutoff):
-        if cutoff is not None and time.time() > cutoff:
-            raise TimeoutError("PollMixin never saw %s return True" % check_f)
-        if check_f():
-            raise PollComplete()
-
 class StallMixin:
     def stall(self, res=None, delay=1):
         d = defer.Deferred()
-- 
2.45.2